diff --git a/agrirouter-sdk-java-api/src/main/java/com/dke/data/agrirouter/api/env/Environment.java b/agrirouter-sdk-java-api/src/main/java/com/dke/data/agrirouter/api/env/Environment.java index a39a264f..997a2ff1 100644 --- a/agrirouter-sdk-java-api/src/main/java/com/dke/data/agrirouter/api/env/Environment.java +++ b/agrirouter-sdk-java-api/src/main/java/com/dke/data/agrirouter/api/env/Environment.java @@ -5,9 +5,10 @@ /** Common Environment, holds some default methods pointing to the QA. */ public interface Environment { - String AGRIROUTER_LOGIN_URL = "/app"; - + /** Template for MQTT connections. */ String MQTT_URL_TEMPLATE = "ssl://%s:%s"; + + /** Link template for the secured onboarding process. */ String SECURED_ONBOARDING_AUTHORIZATION_LINK_TEMPLATE = "/application/%s/authorize?response_type=%s&state=%s&redirect_uri=%s"; @@ -68,16 +69,6 @@ default String getRevokeUrl() { return getRegistrationServiceUrl() + getApiPrefix() + "/registration/onboard/revoke"; } - /** - * Returning the URL to login into the AR. This is necessary, because there are services within - * the UI whiche are only avalailable if the user is logged in. - * - * @return - - */ - default String getAgrirouterLoginUrl() { - return this.getEnvironmentBaseUrl() + AGRIROUTER_LOGIN_URL; - } - /** * Returning the authorization URL for secured onboarding. * diff --git a/agrirouter-sdk-java-api/src/main/java/com/dke/data/agrirouter/api/service/ParameterValidation.java b/agrirouter-sdk-java-api/src/main/java/com/dke/data/agrirouter/api/service/ParameterValidation.java index 541f5450..67798f88 100644 --- a/agrirouter-sdk-java-api/src/main/java/com/dke/data/agrirouter/api/service/ParameterValidation.java +++ b/agrirouter-sdk-java-api/src/main/java/com/dke/data/agrirouter/api/service/ParameterValidation.java @@ -35,22 +35,17 @@ default void businessValidation() { // } - /** Rise an exception if the parameter was not valid. */ - default void rise() { - throw new IllegalParameterDefinitionException( - "Parameter was not defined correctly, please check the values."); - } - /** - * Rise an exception if the parameter was not valid. + * Rise an exception if there has to be at least one valid parameter. * * @param message - */ - default void rise(String message) { + default void rise(String message, String... parameterNames) { + final String joinedParametersNames = String.join(",", parameterNames); throw new IllegalParameterDefinitionException( String.format( - "Parameter was not defined correctly, please check the values. Error message is '%s'.", - message)); + "At least one of the following parameters has to be defined [%s] was not defined correctly, please check the values. '%s'.", + joinedParametersNames, message)); } /** @@ -58,9 +53,10 @@ default void rise(String message) { * * @param o - */ - default void nullCheck(Object o) { + default void nullCheck(String parameterName, Object o) { if (null == o) { - this.rise("The parameter should not have been null, please check your values."); + this.rise( + "The parameter '%s' should not have been null, please check your values.", parameterName); } } @@ -69,9 +65,11 @@ default void nullCheck(Object o) { * * @param s - */ - default void isBlank(String s) { + default void isBlank(String parameterName, String s) { if (StringUtils.isBlank(s)) { - this.rise("The parameter should not have been blank, please check your values."); + this.rise( + "The parameter '%s' should not have been blank, please check your values.", + parameterName); } } @@ -80,10 +78,12 @@ default void isBlank(String s) { * * @param c - */ - default void nullOrEmpty(Collection c) { - nullCheck(c); + default void nullOrEmpty(String parameterName, Collection c) { + nullCheck(parameterName, c); if (c.isEmpty()) { - this.rise("The parameter should not have been empty, please check your values."); + this.rise( + "The parameter '%s' should not have been empty, please check your values.", + parameterName); } } } diff --git a/agrirouter-sdk-java-api/src/main/java/com/dke/data/agrirouter/api/service/messaging/encoding/EncodeMessageService.java b/agrirouter-sdk-java-api/src/main/java/com/dke/data/agrirouter/api/service/messaging/encoding/EncodeMessageService.java index f345522e..b3c44f34 100644 --- a/agrirouter-sdk-java-api/src/main/java/com/dke/data/agrirouter/api/service/messaging/encoding/EncodeMessageService.java +++ b/agrirouter-sdk-java-api/src/main/java/com/dke/data/agrirouter/api/service/messaging/encoding/EncodeMessageService.java @@ -1,7 +1,10 @@ package com.dke.data.agrirouter.api.service.messaging.encoding; +import com.dke.data.agrirouter.api.dto.onboard.OnboardingResponse; import com.dke.data.agrirouter.api.service.parameters.MessageHeaderParameters; +import com.dke.data.agrirouter.api.service.parameters.MessageParameterTuple; import com.dke.data.agrirouter.api.service.parameters.PayloadParameters; +import java.util.List; /** Encoding of messages. */ public interface EncodeMessageService { @@ -15,4 +18,25 @@ public interface EncodeMessageService { */ String encode( MessageHeaderParameters messageHeaderParameters, PayloadParameters payloadParameters); + + /** + * Encode a number of messages. + * + * @param messageParameterTuples - + * @return - + */ + List encode(List messageParameterTuples); + + /** + * Chunk a raw message if necessary. The chunk information and all IDs will be set by the SDK and + * are no longer in control of the application. + * + * @param messageHeaderParameters - + * @param payloadParameters - + * @return - + */ + List chunkAndEncode( + MessageHeaderParameters messageHeaderParameters, + PayloadParameters payloadParameters, + OnboardingResponse onboardingResponse); } diff --git a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/enums/ContentMessageType.kt b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/enums/ContentMessageType.kt index bc16d73a..b937f4b8 100644 --- a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/enums/ContentMessageType.kt +++ b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/enums/ContentMessageType.kt @@ -5,22 +5,22 @@ import agrirouter.technicalmessagetype.Gps /** * Enum containing all the content message types the AR is supporting. */ -enum class ContentMessageType(private val key: String, private val typeUrl: String) : TechnicalMessageType { - ISO_11783_TASKDATA_ZIP("iso:11783:-10:taskdata:zip", ""), +@Suppress("unused") +enum class ContentMessageType(private val key: String, private val typeUrl: String, private val needsChunkinng: Boolean, private val needsBase64Encoding: Boolean) : TechnicalMessageType { + ISO_11783_TASKDATA_ZIP("iso:11783:-10:taskdata:zip", "", true, true), + SHP_SHAPE_ZIP("shp:shape:zip", "", true, true), + DOC_PDF("doc:pdf", "", true, true), + IMG_JPEG("img:jpeg", "", true, true), + IMG_PNG("img:png", "", true, true), + IMG_BMP("img:bmp", "", true, true), + VID_AVI("vid:avi", "", true, true), + VID_MP4("vid:mp4", "", true, true), + VID_WMV("vid:wmv", "", true, true), + GPS_INFO("gps:info", Gps.GPSList.getDescriptor().fullName, false, false), //FIXME Since the spec is not public, we can only use those literals. - ISO_11783_DEVICE_DESCRIPTION("iso:11783:-10:device_description:protobuf", "types.agrirouter.com\\efdi.ISO11783_TaskData"), - ISO_11783_TIME_LOG("iso:11783:-10:time_log:protobuf", "types.agrirouter.com\\efdi.TimeLog"), - - SHP_SHAPE_ZIP("shp:shape:zip", ""), - DOC_PDF("doc:pdf", ""), - IMG_JPEG("img:jpeg", ""), - IMG_PNG("img:png", ""), - IMG_BMP("img:bmp", ""), - VID_AVI("vid:avi", ""), - VID_MP4("vid:mp4", ""), - VID_WMV("vid:wmv", ""), - GPS_INFO("gps:info", Gps.GPSList.getDescriptor().fullName); + ISO_11783_DEVICE_DESCRIPTION("iso:11783:-10:device_description:protobuf", "types.agrirouter.com\\efdi.ISO11783_TaskData", false, false), + ISO_11783_TIME_LOG("iso:11783:-10:time_log:protobuf", "types.agrirouter.com\\efdi.TimeLog", false, false); override fun getKey(): String { return key @@ -29,4 +29,13 @@ enum class ContentMessageType(private val key: String, private val typeUrl: Stri override fun getTypeUrl(): String { return typeUrl } + + override fun getNeedsChunking(): Boolean { + return needsChunkinng + } + + override fun getNeedsBase64Encoding(): Boolean { + return needsBase64Encoding + } + } diff --git a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/enums/SystemMessageType.kt b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/enums/SystemMessageType.kt index 953a091e..b6abe0a5 100644 --- a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/enums/SystemMessageType.kt +++ b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/enums/SystemMessageType.kt @@ -9,6 +9,7 @@ import agrirouter.request.payload.endpoint.SubscriptionOuterClass /** * Enum containing all the content message types the AR is supporting. */ +@Suppress("unused") enum class SystemMessageType(private val key: String, private val typeUrl: String) : TechnicalMessageType { EMPTY("", ""), DKE_CLOUD_ONBOARD_ENDPOINTS("dke:cloud_onboard_endpoints", CloudVirtualizedAppRegistration.OnboardingRequest.getDescriptor().fullName), @@ -30,4 +31,11 @@ enum class SystemMessageType(private val key: String, private val typeUrl: Strin return typeUrl } + override fun getNeedsChunking(): Boolean { + return false + } + + override fun getNeedsBase64Encoding(): Boolean { + return false + } } diff --git a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/enums/TechnicalMessageType.kt b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/enums/TechnicalMessageType.kt index b2293265..181139b6 100644 --- a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/enums/TechnicalMessageType.kt +++ b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/enums/TechnicalMessageType.kt @@ -15,4 +15,14 @@ interface TechnicalMessageType { */ fun getTypeUrl(): String + /** + * Indicates whether the technical message type needs chunking or not. + */ + fun getNeedsChunking(): Boolean + + /** + * Indicates whether the technical message type needs base64 encoding or not. + */ + fun getNeedsBase64Encoding(): Boolean; + } diff --git a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/AuthorizationRequestParameters.kt b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/AuthorizationRequestParameters.kt index 044cca69..6e89233a 100644 --- a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/AuthorizationRequestParameters.kt +++ b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/AuthorizationRequestParameters.kt @@ -18,7 +18,7 @@ class AuthorizationRequestParameters : AbstractParameterBase(), ParameterValidat var responseType: SecuredOnboardingResponseType = SecuredOnboardingResponseType.ONBOARD override fun technicalValidation() { - isBlank(applicationId) + isBlank("applicationId",applicationId) } } \ No newline at end of file diff --git a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/CloudOffboardingParameters.kt b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/CloudOffboardingParameters.kt index 044a5c39..250afc43 100644 --- a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/CloudOffboardingParameters.kt +++ b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/CloudOffboardingParameters.kt @@ -14,12 +14,12 @@ class CloudOffboardingParameters : AbstractParameterBase(), ParameterValidation var endpointIds: List? = null override fun technicalValidation() { - nullCheck(onboardingResponse) - nullCheck(endpointIds) + nullCheck("onboardingResponse",onboardingResponse) + nullCheck("endpointIds",endpointIds) } override fun businessValidation() { - nullOrEmpty(endpointIds) + nullOrEmpty("endpointIds",endpointIds) } } \ No newline at end of file diff --git a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/CloudOnboardingParameters.kt b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/CloudOnboardingParameters.kt index f2e69cdf..6be3305a 100644 --- a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/CloudOnboardingParameters.kt +++ b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/CloudOnboardingParameters.kt @@ -14,12 +14,12 @@ class CloudOnboardingParameters : AbstractParameterBase(), ParameterValidation { var endpointDetails: List? = null override fun technicalValidation() { - nullCheck(onboardingResponse) - nullCheck(endpointDetails) + nullCheck("onboardingResponse",onboardingResponse) + nullCheck("endpointDetails",endpointDetails) } override fun businessValidation() { - nullOrEmpty(endpointDetails) + nullOrEmpty("endpointDetails",endpointDetails) endpointDetails?.forEach { it.validate() } @@ -32,8 +32,8 @@ class CloudOnboardingParameters : AbstractParameterBase(), ParameterValidation { var endpointName: String? = null override fun technicalValidation() { - isBlank(endpointId) - isBlank(endpointName) + isBlank("endpointId",endpointId) + isBlank("endpointName",endpointName) } } diff --git a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/DeleteMessageParameters.kt b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/DeleteMessageParameters.kt index 404f907e..a64483d1 100644 --- a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/DeleteMessageParameters.kt +++ b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/DeleteMessageParameters.kt @@ -20,12 +20,12 @@ class DeleteMessageParameters : AbstractParameterBase(), ParameterValidation { var sentToInSeconds: Long? = null override fun technicalValidation() { - nullCheck(onboardingResponse) + nullCheck("onboardingResponse", onboardingResponse) } override fun businessValidation() { if (null == messageIds && null == senderIds && null == sentFromInSeconds && null == sentToInSeconds) { - rise("There has to be a filter criteria for the query.") + rise("There has to be a filter criteria for the query.", "messageIds", "senderIds", "sentFromInSeconds & sendToInSeconds", "") } } diff --git a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/FetchMessageParameters.kt b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/FetchMessageParameters.kt index 01959a80..911d61a4 100644 --- a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/FetchMessageParameters.kt +++ b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/FetchMessageParameters.kt @@ -12,7 +12,7 @@ open class FetchMessageParameters : AbstractParameterBase(), ParameterValidation var onboardingResponse: OnboardingResponse? = null override fun technicalValidation() { - nullCheck(onboardingResponse) + nullCheck("onboardingResponse",onboardingResponse) } } \ No newline at end of file diff --git a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/ListEndpointsParameters.kt b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/ListEndpointsParameters.kt index 6e4117b3..a6731d23 100644 --- a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/ListEndpointsParameters.kt +++ b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/ListEndpointsParameters.kt @@ -20,9 +20,9 @@ class ListEndpointsParameters : AbstractParameterBase(), ParameterValidation { var unfilteredList: Boolean = false override fun technicalValidation() { - nullCheck(onboardingResponse) - nullCheck(technicalMessageType) - nullCheck(direction) + nullCheck("onboardingResponse",onboardingResponse) + nullCheck("technicalMessageType",technicalMessageType) + nullCheck("direction",direction) } } \ No newline at end of file diff --git a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/MessageConfirmationForAllPendingMessagesParameters.kt b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/MessageConfirmationForAllPendingMessagesParameters.kt index b02d62dc..37c82538 100644 --- a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/MessageConfirmationForAllPendingMessagesParameters.kt +++ b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/MessageConfirmationForAllPendingMessagesParameters.kt @@ -12,7 +12,7 @@ class MessageConfirmationForAllPendingMessagesParameters : AbstractParameterBase var onboardingResponse: OnboardingResponse? = null override fun technicalValidation() { - nullCheck(onboardingResponse) + nullCheck("onboardingResponse",onboardingResponse) } } \ No newline at end of file diff --git a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/MessageConfirmationParameters.kt b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/MessageConfirmationParameters.kt index d3b92503..88502407 100644 --- a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/MessageConfirmationParameters.kt +++ b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/MessageConfirmationParameters.kt @@ -14,8 +14,8 @@ class MessageConfirmationParameters : AbstractParameterBase(), ParameterValidati var messageIds: List? = null override fun technicalValidation() { - nullCheck(onboardingResponse) - nullCheck(messageIds) + nullCheck("onboardingResponse",onboardingResponse) + nullCheck("messageIds",messageIds) } } \ No newline at end of file diff --git a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/MessageHeaderParameters.kt b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/MessageHeaderParameters.kt index b5a7224d..47cd46bb 100644 --- a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/MessageHeaderParameters.kt +++ b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/MessageHeaderParameters.kt @@ -10,7 +10,7 @@ import java.util.* /** * Parameters class. Encapsulation for the services. */ -class MessageHeaderParameters : ParameterValidation { +class MessageHeaderParameters : ParameterValidation { var applicationMessageId: String? = null @@ -29,9 +29,23 @@ class MessageHeaderParameters : ParameterValidation { var metadata: MessageOuterClass.Metadata? = null override fun technicalValidation() { - isBlank(applicationMessageId) - nullCheck(technicalMessageType) - nullCheck(mode) + isBlank("applicationMessageId",applicationMessageId) + nullCheck("technicalMessageType",technicalMessageType) + nullCheck("mode",mode) + } + + /** + * Copy the content of the message header parameters into this class. + */ + fun copy(messageHeaderParameters: MessageHeaderParameters) { + applicationMessageId = messageHeaderParameters.applicationMessageId + applicationMessageSeqNo = messageHeaderParameters.applicationMessageSeqNo + technicalMessageType = messageHeaderParameters.technicalMessageType + teamSetContextId = messageHeaderParameters.teamSetContextId + mode = messageHeaderParameters.mode + recipients = messageHeaderParameters.recipients + chunkInfo = messageHeaderParameters.chunkInfo + metadata = messageHeaderParameters.metadata } } \ No newline at end of file diff --git a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/MessageParameterTuple.kt b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/MessageParameterTuple.kt new file mode 100644 index 00000000..e7eb0630 --- /dev/null +++ b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/MessageParameterTuple.kt @@ -0,0 +1,7 @@ +package com.dke.data.agrirouter.api.service.parameters + +/** + * Containing a tuple for message sending, i.e. used after chunking the messages. + */ +class MessageParameterTuple(var messageHeaderParameters: MessageHeaderParameters, var payloadParameters: PayloadParameters) { +} \ No newline at end of file diff --git a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/MessageQueryParameters.kt b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/MessageQueryParameters.kt index ada86bc6..f3777b63 100644 --- a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/MessageQueryParameters.kt +++ b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/MessageQueryParameters.kt @@ -20,12 +20,12 @@ class MessageQueryParameters : AbstractParameterBase(), ParameterValidation { var sentToInSeconds: Long? = null override fun technicalValidation() { - nullCheck(onboardingResponse) + nullCheck("onboardingResponse", onboardingResponse) } override fun businessValidation() { if (null == messageIds && null == senderIds && null == sentFromInSeconds && null == sentToInSeconds) { - this.rise("There has to be a filter criteria for the query.") + rise("There has to be a filter criteria for the query.", "messageIds", "senderIds", "sentFromInSeconds & sendToInSeconds", "") } } diff --git a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/OnboardingParameters.kt b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/OnboardingParameters.kt index 1754c18f..58aa8a04 100644 --- a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/OnboardingParameters.kt +++ b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/OnboardingParameters.kt @@ -25,12 +25,12 @@ class OnboardingParameters : AbstractParameterBase(), ParameterValidation { var registrationCode: String? = null override fun technicalValidation() { - isBlank(applicationId) - isBlank(uuid) - isBlank(certificationVersionId) - isBlank(gatewayId) - nullCheck(certificationType) - nullCheck(applicationType) - isBlank(registrationCode) + isBlank("applicationId",applicationId) + isBlank("uuid",uuid) + isBlank("certificationVersionId",certificationVersionId) + isBlank("gatewayId",gatewayId) + nullCheck("certificationType",certificationType) + nullCheck("applicationType",applicationType) + isBlank("registrationCode",registrationCode) } } \ No newline at end of file diff --git a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/PayloadParameters.kt b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/PayloadParameters.kt index 1701da67..093cac6d 100644 --- a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/PayloadParameters.kt +++ b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/PayloadParameters.kt @@ -4,6 +4,17 @@ import com.dke.data.agrirouter.api.service.ParameterValidation import com.dke.data.agrirouter.api.service.parameters.base.AbstractParameterBase import com.google.protobuf.ByteString +/** + * Every endpoint can send messages based on its capabilities. The size of a message is however limited. A message contains 2 parts: Header and Body. The limitation of a message is defined as follows: + * - The maximum body size is equivalent of 1024000 characters/signs + * - Since the chunking is performed on the raw message data this means, that we have to lower the MAX_LENGTH_FOR_MESSAGES to allow Base64 encoding afterwards. + * - Total message size is limited to 1468000 characters/signs + * - Messages that are above this limit will be rejected. + * The AR will return an error indicating that the message size is above the limit. + * If the message size is above 5 MB the AR will not return any error. In order to send messages with sizes above threshold, these messages must be split into chunks with the above limit. + */ +const val MAX_LENGTH_FOR_RAW_MESSAGE_CONTENT = 767997 + /** * Parameters class. Encapsulation for the services. */ @@ -14,8 +25,30 @@ class PayloadParameters : AbstractParameterBase(), ParameterValidation { var value: ByteString? = null override fun technicalValidation() { - nullCheck(typeUrl) - nullCheck(value) + nullCheck("typeUrl",typeUrl) + nullCheck("value",value) + } + + /** + * Determining whether the message should be chunked. + */ + fun shouldBeChunked(): Boolean { + return value!!.toStringUtf8().length > MAX_LENGTH_FOR_RAW_MESSAGE_CONTENT + } + + /** + * The maximum length for messages / the payload. + */ + fun maxLengthForMessages(): Int { + return MAX_LENGTH_FOR_RAW_MESSAGE_CONTENT + } + + fun copyFrom(payload: PayloadParameters) { + applicationMessageId = payload.applicationMessageId + teamsetContextId = payload.teamsetContextId + sequenceNumber = payload.sequenceNumber + typeUrl = payload.typeUrl + value = payload.value } } \ No newline at end of file diff --git a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/RegistrationCodeRequestParameters.kt b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/RegistrationCodeRequestParameters.kt index 88aa2e9e..e6b45b7c 100644 --- a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/RegistrationCodeRequestParameters.kt +++ b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/RegistrationCodeRequestParameters.kt @@ -11,7 +11,7 @@ class RegistrationCodeRequestParameters : AbstractParameterBase(), ParameterVali lateinit var applicationId: String override fun technicalValidation() { - isBlank(applicationId) + isBlank("applicationId",applicationId) } diff --git a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/RevokeParameters.kt b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/RevokeParameters.kt index c3565f4c..468e8e62 100644 --- a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/RevokeParameters.kt +++ b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/RevokeParameters.kt @@ -18,14 +18,14 @@ class RevokeParameters : ParameterValidation { var publicKey: String? = null override fun technicalValidation() { - isBlank(applicationId) - isBlank(accountId) - isBlank(privateKey) - isBlank(publicKey) - nullCheck(endpointIds) + isBlank("applicationId",applicationId) + isBlank("accountId",accountId) + isBlank("privateKey",privateKey) + isBlank("publicKey",publicKey) + nullCheck("endpointIds",endpointIds) } override fun businessValidation() { - nullOrEmpty(endpointIds) + nullOrEmpty("endpointIds",endpointIds) } } \ No newline at end of file diff --git a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/SecuredOnboardingParameters.kt b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/SecuredOnboardingParameters.kt index a39a4c01..1c711345 100644 --- a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/SecuredOnboardingParameters.kt +++ b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/SecuredOnboardingParameters.kt @@ -26,14 +26,14 @@ class SecuredOnboardingParameters : AbstractParameterBase(), ParameterValidation var registrationCode: String? = null override fun technicalValidation() { - isBlank(applicationId) - isBlank(privateKey) - isBlank(publicKey) - isBlank(uuid) - isBlank(certificationVersionId) - isBlank(gatewayId) - isBlank(registrationCode) - nullCheck(certificationType) + isBlank("applicationId",applicationId) + isBlank("privateKey",privateKey) + isBlank("publicKey",publicKey) + isBlank("uuid",uuid) + isBlank("certificationVersionId",certificationVersionId) + isBlank("gatewayId",gatewayId) + isBlank("registrationCode",registrationCode) + nullCheck("certificationType",certificationType) } } \ No newline at end of file diff --git a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/SendMessageParameters.kt b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/SendMessageParameters.kt index 4e1d740e..4d4deeaa 100644 --- a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/SendMessageParameters.kt +++ b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/SendMessageParameters.kt @@ -14,12 +14,12 @@ open class SendMessageParameters : AbstractParameterBase(), ParameterValidation var encodedMessages: List? = null override fun technicalValidation() { - nullCheck(onboardingResponse) - nullCheck(encodedMessages) + nullCheck("onboardingResponse",onboardingResponse) + nullCheck("encodedMessages",encodedMessages) } override fun businessValidation() { - nullOrEmpty(encodedMessages) + nullOrEmpty("encodedMessages",encodedMessages) } } \ No newline at end of file diff --git a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/SetCapabilitiesParameters.kt b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/SetCapabilitiesParameters.kt index 39827579..d7a7e478 100644 --- a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/SetCapabilitiesParameters.kt +++ b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/SetCapabilitiesParameters.kt @@ -28,17 +28,17 @@ class SetCapabilitiesParameters : AbstractParameterBase(), ParameterValidation { var direction: Capabilities.CapabilitySpecification.Direction? = null override fun technicalValidation() { - nullCheck(technicalMessageType) - nullCheck(direction) + nullCheck("technicalMessageType",technicalMessageType) + nullCheck("direction",direction) } } override fun technicalValidation() { - nullCheck(onboardingResponse) - isBlank(applicationId) - isBlank(certificationVersionId) - nullCheck(capabilitiesParameters) + nullCheck("onboardingResponse",onboardingResponse) + isBlank("applicationId",applicationId) + isBlank("certificationVersionId",certificationVersionId) + nullCheck("capabilitiesParameters",capabilitiesParameters) capabilitiesParameters?.forEach { c -> c.validate() } } diff --git a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/SetSubscriptionParameters.kt b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/SetSubscriptionParameters.kt index 2d973a41..6663da44 100644 --- a/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/SetSubscriptionParameters.kt +++ b/agrirouter-sdk-java-api/src/main/kotlin/com/dke/data/agrirouter/api/service/parameters/SetSubscriptionParameters.kt @@ -21,14 +21,14 @@ class SetSubscriptionParameters : AbstractParameterBase(), ParameterValidation { var position: Boolean = false override fun technicalValidation() { - nullCheck(technicalMessageType) + nullCheck("technicalMessageType",technicalMessageType) } } var subscriptions: List = ArrayList() override fun technicalValidation() { - nullCheck(onboardingResponse) + nullCheck("onboardingResponse",onboardingResponse) } } \ No newline at end of file diff --git a/agrirouter-sdk-java-impl/pom.xml b/agrirouter-sdk-java-impl/pom.xml index 86a1dec1..e72ac42c 100644 --- a/agrirouter-sdk-java-impl/pom.xml +++ b/agrirouter-sdk-java-impl/pom.xml @@ -60,6 +60,10 @@ org.apache.httpcomponents httpcore + + com.google.guava + guava + diff --git a/agrirouter-sdk-java-impl/src/main/java/com/dke/data/agrirouter/impl/ChunkContextIdService.java b/agrirouter-sdk-java-impl/src/main/java/com/dke/data/agrirouter/impl/ChunkContextIdService.java new file mode 100644 index 00000000..a8c5a907 --- /dev/null +++ b/agrirouter-sdk-java-impl/src/main/java/com/dke/data/agrirouter/impl/ChunkContextIdService.java @@ -0,0 +1,16 @@ +package com.dke.data.agrirouter.impl; + +import java.util.UUID; + +/** Service to provide a unique chunk context id. */ +public class ChunkContextIdService { + + /** + * Generate a unique id by using the internal UUID implementation. + * + * @return - + */ + public static String generateChunkContextId() { + return UUID.randomUUID().toString(); + } +} diff --git a/agrirouter-sdk-java-impl/src/main/java/com/dke/data/agrirouter/impl/messaging/encoding/EncodeMessageServiceImpl.java b/agrirouter-sdk-java-impl/src/main/java/com/dke/data/agrirouter/impl/messaging/encoding/EncodeMessageServiceImpl.java index 7a571fd9..9c4abf35 100644 --- a/agrirouter-sdk-java-impl/src/main/java/com/dke/data/agrirouter/impl/messaging/encoding/EncodeMessageServiceImpl.java +++ b/agrirouter-sdk-java-impl/src/main/java/com/dke/data/agrirouter/impl/messaging/encoding/EncodeMessageServiceImpl.java @@ -1,25 +1,47 @@ package com.dke.data.agrirouter.impl.messaging.encoding; +import agrirouter.commons.Chunk; import agrirouter.request.Request; +import com.dke.data.agrirouter.api.dto.onboard.OnboardingResponse; import com.dke.data.agrirouter.api.exception.CouldNotEncodeMessageException; import com.dke.data.agrirouter.api.service.messaging.encoding.EncodeMessageService; import com.dke.data.agrirouter.api.service.parameters.MessageHeaderParameters; +import com.dke.data.agrirouter.api.service.parameters.MessageParameterTuple; import com.dke.data.agrirouter.api.service.parameters.PayloadParameters; import com.dke.data.agrirouter.api.util.TimestampUtil; +import com.dke.data.agrirouter.impl.ChunkContextIdService; import com.dke.data.agrirouter.impl.NonEnvironmentalService; +import com.dke.data.agrirouter.impl.common.MessageIdService; +import com.dke.data.agrirouter.impl.messaging.SequenceNumberService; +import com.google.common.base.Splitter; import com.google.protobuf.Any; +import com.google.protobuf.ByteString; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.Base64; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; /** Internal service implementation. */ +@SuppressWarnings("ConstantConditions") public class EncodeMessageServiceImpl extends NonEnvironmentalService implements EncodeMessageService { + /** + * Encode a message. In this case chunking will be done by the application and not by the SDK. + * + * @param messageHeaderParameters - + * @param payloadParameters - + * @return Single message, encoded by the SDK. + */ public String encode( MessageHeaderParameters messageHeaderParameters, PayloadParameters payloadParameters) { - this.logMethodBegin(messageHeaderParameters, payloadParameters); + logMethodBegin(messageHeaderParameters, payloadParameters); if (null == messageHeaderParameters || null == payloadParameters) { throw new IllegalArgumentException("Parameters cannot be NULL"); @@ -29,26 +51,154 @@ public String encode( try (ByteArrayOutputStream streamedMessage = new ByteArrayOutputStream()) { - this.getNativeLogger().trace("Encode header."); - this.header(messageHeaderParameters).writeDelimitedTo(streamedMessage); + getNativeLogger().trace("Encode header."); + header(messageHeaderParameters).writeDelimitedTo(streamedMessage); - this.getNativeLogger().trace("Encode payload."); - this.payload(payloadParameters).writeDelimitedTo(streamedMessage); + getNativeLogger().trace("Encode payload."); + payload(payloadParameters).writeDelimitedTo(streamedMessage); - this.getNativeLogger().trace("Encoding message."); + getNativeLogger().trace("Encoding message."); String encodedMessage = Base64.getEncoder().encodeToString(streamedMessage.toByteArray()); - this.logMethodEnd(encodedMessage); + logMethodEnd(encodedMessage); return encodedMessage; } catch (IOException e) { throw new CouldNotEncodeMessageException(e); } } + /** + * Encode a number of messages. + * + * @param messageParameterTuples - + * @return - + */ + public List encode(List messageParameterTuples) { + return messageParameterTuples.stream() + .map( + messageParameterTuple -> + encode( + messageParameterTuple.getMessageHeaderParameters(), + messageParameterTuple.getPayloadParameters())) + .collect(Collectors.toList()); + } + + /** + * Chunk and add the Base64 encoding for a message if necessary. If there is only one chunk, the + * single chunk will be returned as Base64 encoded value. The chunk information and all IDs + * will be set by the SDK and are no longer in control of the application. + * + * @param messageHeaderParameters - + * @param payloadParameters Content of the message. It shall not be Base64 encoded before. + * @return - + */ + public List chunkAndEncode( + MessageHeaderParameters messageHeaderParameters, + PayloadParameters payloadParameters, + OnboardingResponse onboardingResponse) { + logMethodBegin(messageHeaderParameters, payloadParameters); + + if (null == messageHeaderParameters + || null == payloadParameters + || null == onboardingResponse) { + throw new IllegalArgumentException("Parameters cannot be NULL"); + } + messageHeaderParameters.validate(); + payloadParameters.validate(); + + if (messageHeaderParameters.getTechnicalMessageType().getNeedsChunking()) { + if (payloadParameters.shouldBeChunked()) { + getNativeLogger() + .debug( + "The message should be chunked, current size of the payload ({}) is above the limitation.", + payloadParameters.getValue().toStringUtf8().length()); + String wholeMessage = payloadParameters.getValue().toStringUtf8(); + final List messageChunks = + Splitter.fixedLength(payloadParameters.maxLengthForMessages()) + .splitToList(wholeMessage); + List tuples = new ArrayList<>(); + AtomicInteger chunkNr = new AtomicInteger(1); + final String chunkContextId = ChunkContextIdService.generateChunkContextId(); + messageChunks.forEach( + chunk -> { + final String messageIdForChunk = MessageIdService.generateMessageId(); + final long sequenceNumberForChunk = + SequenceNumberService.generateSequenceNumberForEndpoint(onboardingResponse); + + final MessageHeaderParameters header = new MessageHeaderParameters(); + header.copy(messageHeaderParameters); + header.setApplicationMessageId(messageIdForChunk); + header.setApplicationMessageSeqNo(sequenceNumberForChunk); + Chunk.ChunkComponent.Builder chunkInfo = Chunk.ChunkComponent.newBuilder(); + chunkInfo.setContextId(chunkContextId); + chunkInfo.setCurrent(chunkNr.get()); + chunkInfo.setTotal(messageChunks.size()); + chunkInfo.setTotalSize(wholeMessage.length()); + header.setChunkInfo(chunkInfo.build()); + + final PayloadParameters payload = new PayloadParameters(); + payload.copyFrom(payloadParameters); + payload.setValue( + ByteString.copyFromUtf8( + Base64.getEncoder().encodeToString(chunk.getBytes(StandardCharsets.UTF_8)))); + + tuples.add(new MessageParameterTuple(header, payload)); + + chunkNr.getAndIncrement(); + }); + return tuples; + } else { + getNativeLogger() + .debug( + "The message is not chunked since the current size of the payload ({}) is not above the limitation and the technical message type '{}' does support chunking.", + payloadParameters.getValue().toStringUtf8().length(), + messageHeaderParameters.getTechnicalMessageType().getKey()); + getNativeLogger() + .debug("The content is encoded, since in other cases the content is encoded as well."); + final PayloadParameters payload = new PayloadParameters(); + payload.copyFrom(payloadParameters); + payload.setValue( + ByteString.copyFromUtf8( + Base64.getEncoder() + .encodeToString( + payloadParameters + .getValue() + .toStringUtf8() + .getBytes(StandardCharsets.UTF_8)))); + return Collections.singletonList( + new MessageParameterTuple(messageHeaderParameters, payload)); + } + } else { + if (messageHeaderParameters.getTechnicalMessageType().getNeedsBase64Encoding()) { + getNativeLogger() + .debug( + "The message type needs to be base64 encoded, therefore we are encoding the raw value."); + final PayloadParameters payload = new PayloadParameters(); + payload.copyFrom(payloadParameters); + payload.setValue( + ByteString.copyFromUtf8( + Base64.getEncoder() + .encodeToString( + payloadParameters + .getValue() + .toStringUtf8() + .getBytes(StandardCharsets.UTF_8)))); + return Collections.singletonList( + new MessageParameterTuple(messageHeaderParameters, payload)); + } else { + getNativeLogger() + .debug( + "The message type does not need base 64 encoding, we are returning the tuple 'as it is'."); + return Collections.singletonList( + new MessageParameterTuple(messageHeaderParameters, payloadParameters)); + } + } + } + private Request.RequestEnvelope header(MessageHeaderParameters parameters) { - this.logMethodBegin(parameters); + logMethodBegin(parameters); - this.getNativeLogger().trace("Create message header."); + getNativeLogger().trace("Create message header."); agrirouter.request.Request.RequestEnvelope.Builder messageHeader = Request.RequestEnvelope.newBuilder(); messageHeader.setApplicationMessageId(parameters.getApplicationMessageId()); @@ -69,17 +219,17 @@ private Request.RequestEnvelope header(MessageHeaderParameters parameters) { } messageHeader.setTimestamp(new TimestampUtil().current()); - this.getNativeLogger().trace("Build message envelope."); + getNativeLogger().trace("Build message envelope."); Request.RequestEnvelope requestEnvelope = messageHeader.build(); - this.logMethodEnd(requestEnvelope); + logMethodEnd(requestEnvelope); return requestEnvelope; } private Request.RequestPayloadWrapper payload(PayloadParameters parameters) { - this.logMethodBegin(parameters); + logMethodBegin(parameters); - this.getNativeLogger().trace("Create message payload."); + getNativeLogger().trace("Create message payload."); Request.RequestPayloadWrapper.Builder messagePayload = Request.RequestPayloadWrapper.newBuilder(); Any.Builder builder = Any.newBuilder(); @@ -87,10 +237,10 @@ private Request.RequestPayloadWrapper payload(PayloadParameters parameters) { builder.setValue(parameters.getValue()); messagePayload.setDetails(builder.build()); - this.getNativeLogger().trace("Message message payload wrapper."); + getNativeLogger().trace("Message message payload wrapper."); Request.RequestPayloadWrapper requestPayloadWrapper = messagePayload.build(); - this.logMethodEnd(requestPayloadWrapper); + logMethodEnd(requestPayloadWrapper); return requestPayloadWrapper; } } diff --git a/agrirouter-sdk-java-impl/src/main/java/com/dke/data/agrirouter/impl/messaging/rest/MessageFetcher.java b/agrirouter-sdk-java-impl/src/main/java/com/dke/data/agrirouter/impl/messaging/rest/MessageFetcher.java index 14ee435d..bad0eb38 100644 --- a/agrirouter-sdk-java-impl/src/main/java/com/dke/data/agrirouter/impl/messaging/rest/MessageFetcher.java +++ b/agrirouter-sdk-java-impl/src/main/java/com/dke/data/agrirouter/impl/messaging/rest/MessageFetcher.java @@ -9,10 +9,14 @@ import java.util.Optional; import javax.ws.rs.core.Response; import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; /** Interface to fetch messages for the HTTP implementation by polling the outbox. */ public interface MessageFetcher extends ResponseValidator { + Logger LOGGER = LogManager.getLogger(); + int MAX_TRIES_BEFORE_FAILURE = 10; long DEFAULT_INTERVAL = 500; @@ -28,7 +32,11 @@ public interface MessageFetcher extends ResponseValidator { default Optional poll( FetchMessageParameters fetchMessageParameters, CancellationToken cancellationToken) { fetchMessageParameters.validate(); + int nrOfTries = 1; while (cancellationToken.isNotCancelled()) { + LOGGER.debug( + "The cancellation token is not cancelled, we have another try. This is try number {}.", + nrOfTries); Response response = RequestFactory.securedRequest( Objects.requireNonNull(fetchMessageParameters.getOnboardingResponse()) diff --git a/agrirouter-sdk-java-impl/src/test/java/com/dke/data/agrirouter/impl/messaging/encoding/EncodeMessageServiceImplTest.java b/agrirouter-sdk-java-impl/src/test/java/com/dke/data/agrirouter/impl/messaging/encoding/EncodeMessageServiceImplTest.java index a6d5ec1e..3840a6fc 100644 --- a/agrirouter-sdk-java-impl/src/test/java/com/dke/data/agrirouter/impl/messaging/encoding/EncodeMessageServiceImplTest.java +++ b/agrirouter-sdk-java-impl/src/test/java/com/dke/data/agrirouter/impl/messaging/encoding/EncodeMessageServiceImplTest.java @@ -5,16 +5,103 @@ import agrirouter.request.Request; import agrirouter.request.payload.endpoint.Capabilities; import com.dke.data.agrirouter.api.dto.encoding.DecodeMessageResponse; +import com.dke.data.agrirouter.api.dto.onboard.OnboardingResponse; +import com.dke.data.agrirouter.api.enums.ContentMessageType; import com.dke.data.agrirouter.api.enums.SystemMessageType; import com.dke.data.agrirouter.api.service.messaging.encoding.EncodeMessageService; import com.dke.data.agrirouter.api.service.parameters.MessageHeaderParameters; +import com.dke.data.agrirouter.api.service.parameters.MessageParameterTuple; import com.dke.data.agrirouter.api.service.parameters.PayloadParameters; +import com.dke.data.agrirouter.api.service.parameters.PayloadParametersKt; import com.google.protobuf.ByteString; +import java.util.List; +import org.apache.commons.lang3.RandomStringUtils; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; class EncodeMessageServiceImplTest { + @Test + void givenEmptyMessageWhenChunkingThenTheImplementationShouldReturnTheRightNumberOfChunks() { + EncodeMessageService encodeMessageService = new EncodeMessageServiceImpl(); + + ByteString toSendMessage = ByteString.copyFromUtf8(""); + MessageHeaderParameters messageHeaderParameters = getMessageHeaderParameters(); + messageHeaderParameters.setTechnicalMessageType(ContentMessageType.ISO_11783_TASKDATA_ZIP); + PayloadParameters payloadParameters = getPayloadParameters(toSendMessage); + + final List chunks = + encodeMessageService.chunkAndEncode( + messageHeaderParameters, payloadParameters, fakeOnboardingResponse()); + Assertions.assertEquals(1, chunks.size()); + } + + @Test + void + givenSingleChunkMessageWhenChunkingThenTheImplementationShouldReturnTheRightNumberOfChunks() { + EncodeMessageService encodeMessageService = new EncodeMessageServiceImpl(); + + ByteString toSendMessage = ByteString.copyFromUtf8("secretMessage"); + MessageHeaderParameters messageHeaderParameters = getMessageHeaderParameters(); + messageHeaderParameters.setTechnicalMessageType(ContentMessageType.ISO_11783_TASKDATA_ZIP); + PayloadParameters payloadParameters = getPayloadParameters(toSendMessage); + + final List chunks = + encodeMessageService.chunkAndEncode( + messageHeaderParameters, payloadParameters, fakeOnboardingResponse()); + Assertions.assertEquals(1, chunks.size()); + } + + @Test + void + givenSingleChunkMessageWithMaxSizeWhenChunkingThenTheImplementationShouldReturnTheRightNumberOfChunks() { + EncodeMessageService encodeMessageService = new EncodeMessageServiceImpl(); + + ByteString toSendMessage = + ByteString.copyFromUtf8( + RandomStringUtils.randomAlphabetic( + PayloadParametersKt.MAX_LENGTH_FOR_RAW_MESSAGE_CONTENT)); + MessageHeaderParameters messageHeaderParameters = getMessageHeaderParameters(); + messageHeaderParameters.setTechnicalMessageType(ContentMessageType.ISO_11783_TASKDATA_ZIP); + PayloadParameters payloadParameters = getPayloadParameters(toSendMessage); + + final List chunks = + encodeMessageService.chunkAndEncode( + messageHeaderParameters, payloadParameters, fakeOnboardingResponse()); + Assertions.assertEquals(1, chunks.size()); + } + + @Test + @SuppressWarnings("ConstantConditions") + void + givenMultipleChunkMessageWithMaxSizeWhenChunkingThenTheImplementationShouldReturnTheRightNumberOfChunks() { + EncodeMessageService encodeMessageService = new EncodeMessageServiceImpl(); + + ByteString toSendMessage = ByteString.copyFromUtf8(RandomStringUtils.randomAlphabetic(1024001)); + MessageHeaderParameters messageHeaderParameters = getMessageHeaderParameters(); + messageHeaderParameters.setTechnicalMessageType(ContentMessageType.ISO_11783_TASKDATA_ZIP); + PayloadParameters payloadParameters = getPayloadParameters(toSendMessage); + + final List chunks = + encodeMessageService.chunkAndEncode( + messageHeaderParameters, payloadParameters, fakeOnboardingResponse()); + Assertions.assertEquals(2, chunks.size()); + + Assertions.assertEquals( + 2, chunks.get(0).getMessageHeaderParameters().getChunkInfo().getTotal()); + Assertions.assertEquals( + 2, chunks.get(1).getMessageHeaderParameters().getChunkInfo().getTotal()); + + Assertions.assertEquals( + 1, chunks.get(0).getMessageHeaderParameters().getChunkInfo().getCurrent()); + Assertions.assertEquals( + 2, chunks.get(1).getMessageHeaderParameters().getChunkInfo().getCurrent()); + + Assertions.assertEquals( + chunks.get(0).getMessageHeaderParameters().getChunkInfo().getContextId(), + chunks.get(1).getMessageHeaderParameters().getChunkInfo().getContextId()); + } + @Test void givenValidParametersEncodeAndDecodeBackShouldNotFail() { EncodeMessageService encodeMessageService = new EncodeMessageServiceImpl(); @@ -83,4 +170,10 @@ private PayloadParameters getPayloadParameters(ByteString toSendMessage) { payloadParameters.setValue(toSendMessage); return payloadParameters; } + + private OnboardingResponse fakeOnboardingResponse() { + OnboardingResponse onboardingResponse = new OnboardingResponse(); + onboardingResponse.setSensorAlternateId("THIS_IS_FAKE"); + return onboardingResponse; + } } diff --git a/agrirouter-sdk-java-tests/pom.xml b/agrirouter-sdk-java-tests/pom.xml index 37a38234..bbcad8ed 100644 --- a/agrirouter-sdk-java-tests/pom.xml +++ b/agrirouter-sdk-java-tests/pom.xml @@ -36,6 +36,10 @@ org.junit.jupiter junit-jupiter-api + + org.junit.jupiter + junit-jupiter-params + org.glassfish.jersey.inject jersey-hk2 diff --git a/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/AbstractIntegrationTest.java b/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/AbstractIntegrationTest.java index 23e9e6b5..deda31e1 100644 --- a/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/AbstractIntegrationTest.java +++ b/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/AbstractIntegrationTest.java @@ -1,10 +1,39 @@ package com.dke.data.agrirouter.test; +import java.util.concurrent.TimeUnit; import org.apache.commons.lang3.NotImplementedException; /** Abstract implementation for all integration tests. */ public abstract class AbstractIntegrationTest { + /** + * Since there are multiple problems with the stability of the QA env we define dedicated + * constants for message fetching. + */ + protected int MAX_TRIES_BEFORE_FAILURE = 10; + + protected long DEFAULT_INTERVAL = 5000; + + /** + * Wait for the AR to process the messages. Since the QA has some stability problems, we will wait + * up to 30 seconds until the AR has processed the messages. + * + * @throws InterruptedException - + */ + protected void waitForTheAgrirouterToProcessSingleMessage() throws InterruptedException { + Thread.sleep(TimeUnit.SECONDS.toMillis(30)); + } + + /** + * Wait for the AR to process the messages. Since the QA has some stability problems, we will wait + * up to one minute until the AR has processed the messages. + * + * @throws InterruptedException - + */ + protected void waitForTheAgrirouterToProcessMultipleMessages() throws InterruptedException { + Thread.sleep(TimeUnit.SECONDS.toMillis(60)); + } + /** Farming software for integration testing. */ protected Application farmingSoftware = new Application() { diff --git a/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/messaging/rest/CancellationTokenPollingTest.java b/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/messaging/rest/CancellationTokenPollingTest.java index 96a1da89..aec60d98 100644 --- a/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/messaging/rest/CancellationTokenPollingTest.java +++ b/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/messaging/rest/CancellationTokenPollingTest.java @@ -1,8 +1,5 @@ package com.dke.data.agrirouter.test.messaging.rest; -import static com.dke.data.agrirouter.impl.messaging.rest.MessageFetcher.DEFAULT_INTERVAL; -import static com.dke.data.agrirouter.impl.messaging.rest.MessageFetcher.MAX_TRIES_BEFORE_FAILURE; - import com.dke.data.agrirouter.api.cancellation.CancellationToken; import com.dke.data.agrirouter.api.cancellation.DefaultCancellationToken; import com.dke.data.agrirouter.api.dto.messaging.FetchMessageResponse; @@ -22,7 +19,7 @@ class CancellationTokenPollingTest extends AbstractIntegrationTest { @Test - @Timeout(value = 15) + @Timeout(15) @SuppressWarnings("deprecation") void givenExistingImplementationOfTheCancellationTokenWhenPollingMessagesThenTheDefaultParametersShouldStillInfluenceTheBehavior() @@ -38,7 +35,7 @@ class CancellationTokenPollingTest extends AbstractIntegrationTest { } @Test - @Timeout(value = 1) + @Timeout(1) @SuppressWarnings("deprecation") void givenExistingImplementationOfTheCancellationTokenWhenPollingMessagesThenTheCustomParametersShouldStillInfluenceTheBehavior() @@ -54,7 +51,7 @@ class CancellationTokenPollingTest extends AbstractIntegrationTest { } @Test - @Timeout(15) + @Timeout(60) void givenDefaultImplementationOfTheCancellationTokenWhenPollingMessagesThenTheCancellationTokenShouldInfluenceTheBehavior() throws IOException { diff --git a/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/messaging/rest/CloudOffboardingServiceTest.java b/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/messaging/rest/CloudOffboardingServiceTest.java index b44b0db4..e8bd978a 100644 --- a/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/messaging/rest/CloudOffboardingServiceTest.java +++ b/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/messaging/rest/CloudOffboardingServiceTest.java @@ -1,7 +1,5 @@ package com.dke.data.agrirouter.test.messaging.rest; -import static com.dke.data.agrirouter.impl.messaging.rest.MessageFetcher.DEFAULT_INTERVAL; -import static com.dke.data.agrirouter.impl.messaging.rest.MessageFetcher.MAX_TRIES_BEFORE_FAILURE; import static com.dke.data.agrirouter.test.OnboardingResponseRepository.Identifier; import static com.dke.data.agrirouter.test.OnboardingResponseRepository.read; @@ -27,9 +25,9 @@ import java.util.Collections; import java.util.List; import java.util.Optional; -import java.util.concurrent.TimeUnit; import org.apache.http.HttpStatus; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; class CloudOffboardingServiceTest extends AbstractIntegrationTest { @@ -37,10 +35,19 @@ class CloudOffboardingServiceTest extends AbstractIntegrationTest { public static final String EXTERNAL_ID = "8c31e156-3c29-4b46-863c-5e49b405b344"; public static final String ENDPOINT_NAME = "CLOUD-OFFBOARDING-SERVICE-TEST"; + /** + * The endpoint ID for a former test run. If the endpoint is still available, then there could be + * a chance to remove it. This has to be set manually. + */ + public static final String VCU_ENDPOINT_ID_FOR_FORMER_TEST_RUN = + "bbfdcaed-9228-42a9-ab51-9e226cb314d1"; + private OnboardingResponse virtualCommunicationUnit; @BeforeEach void onboardVirtualCu() throws Throwable { + offboardExistingVirtualCUFromFormerTestRun(); + CloudOnboardingService cloudOnboardingService = new CloudOnboardingServiceImpl(); CloudOnboardingParameters parameters = new CloudOnboardingParameters(); CloudOnboardingParameters.EndpointDetailsParameters endpointDetails = @@ -51,7 +58,7 @@ void onboardVirtualCu() throws Throwable { parameters.setOnboardingResponse(read(Identifier.TELEMETRY_PLATFORM)); cloudOnboardingService.send(parameters); - Thread.sleep(TimeUnit.SECONDS.toMillis(5)); + waitForTheAgrirouterToProcessSingleMessage(); FetchMessageService fetchMessageService = new FetchMessageServiceImpl(); Optional> fetchMessageResponses = @@ -91,7 +98,26 @@ void onboardVirtualCu() throws Throwable { Assertions.assertNotNull(virtualCommunicationUnit.getConnectionCriteria()); } + private void offboardExistingVirtualCUFromFormerTestRun() throws Throwable { + CloudOffboardingService cloudOffboardingService = new CloudOffboardingServiceImpl(); + CloudOffboardingParameters parameters = new CloudOffboardingParameters(); + parameters.setEndpointIds(Collections.singletonList(VCU_ENDPOINT_ID_FOR_FORMER_TEST_RUN)); + parameters.setOnboardingResponse(read(Identifier.TELEMETRY_PLATFORM)); + cloudOffboardingService.send(parameters); + FetchMessageService fetchMessageService = new FetchMessageServiceImpl(); + Optional> fetchMessageResponses = + fetchMessageService.fetch( + read(Identifier.TELEMETRY_PLATFORM), + new DefaultCancellationToken(MAX_TRIES_BEFORE_FAILURE, DEFAULT_INTERVAL)); + waitForTheAgrirouterToProcessSingleMessage(); + Assertions.assertTrue(fetchMessageResponses.isPresent()); + Assertions.assertEquals(1, fetchMessageResponses.get().size()); + Assertions.assertNotNull(fetchMessageResponses.get().get(0).getCommand()); + } + @Test + @Disabled( + "Since there are multiple problems with the environment, the test is currently disabled.") void givenValidSensorIdWhenOffboardingVirtualCuThenTheOffbardingShouldBeSuccessful() throws Throwable { CloudOffboardingService cloudOffboardingService = new CloudOffboardingServiceImpl(); @@ -101,7 +127,7 @@ void givenValidSensorIdWhenOffboardingVirtualCuThenTheOffbardingShouldBeSuccessf parameters.setOnboardingResponse(read(Identifier.TELEMETRY_PLATFORM)); cloudOffboardingService.send(parameters); - Thread.sleep(TimeUnit.SECONDS.toMillis(5)); + waitForTheAgrirouterToProcessSingleMessage(); FetchMessageService fetchMessageService = new FetchMessageServiceImpl(); Optional> fetchMessageResponses = diff --git a/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/messaging/rest/CloudOnboardingServiceTest.java b/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/messaging/rest/CloudOnboardingServiceTest.java index 01c70cca..fafe984f 100644 --- a/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/messaging/rest/CloudOnboardingServiceTest.java +++ b/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/messaging/rest/CloudOnboardingServiceTest.java @@ -1,7 +1,5 @@ package com.dke.data.agrirouter.test.messaging.rest; -import static com.dke.data.agrirouter.impl.messaging.rest.MessageFetcher.DEFAULT_INTERVAL; -import static com.dke.data.agrirouter.impl.messaging.rest.MessageFetcher.MAX_TRIES_BEFORE_FAILURE; import static com.dke.data.agrirouter.test.OnboardingResponseRepository.Identifier; import static com.dke.data.agrirouter.test.OnboardingResponseRepository.read; @@ -27,9 +25,9 @@ import java.util.Collections; import java.util.List; import java.util.Optional; -import java.util.concurrent.TimeUnit; import org.apache.http.HttpStatus; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; class CloudOnboardingServiceTest extends AbstractIntegrationTest { @@ -37,10 +35,19 @@ class CloudOnboardingServiceTest extends AbstractIntegrationTest { public static final String EXTERNAL_ID = "8c31e156-3c29-4b46-863c-5e49b405b343"; public static final String ENDPOINT_NAME = "CLOUD-ONBOARDING-SERVICE-TEST"; + /** + * The endpoint ID for a former test run. If the endpoint is still available, then there could be + * a chance to remove it. This has to be set manually. + */ + public static final String VCU_ENDPOINT_ID_FOR_FORMER_TEST_RUN = + "4e3af0ec-efb1-4109-8d3d-1910094c09d9"; + private OnboardingResponse virtualCommunicationUnit; @AfterEach void offboardVirtualCu() throws Throwable { + offboardExistingVirtualCUFromFormerTestRun(); + CloudOffboardingService cloudOffboardingService = new CloudOffboardingServiceImpl(); CloudOffboardingParameters parameters = new CloudOffboardingParameters(); parameters.setEndpointIds( @@ -48,7 +55,7 @@ void offboardVirtualCu() throws Throwable { parameters.setOnboardingResponse(read(Identifier.TELEMETRY_PLATFORM)); cloudOffboardingService.send(parameters); - Thread.sleep(TimeUnit.SECONDS.toMillis(5)); + waitForTheAgrirouterToProcessSingleMessage(); FetchMessageService fetchMessageService = new FetchMessageServiceImpl(); Optional> fetchMessageResponses = @@ -71,7 +78,26 @@ void offboardVirtualCu() throws Throwable { decodeMessageResponse.getResponseEnvelope().getResponseCode()); } + private void offboardExistingVirtualCUFromFormerTestRun() throws Throwable { + CloudOffboardingService cloudOffboardingService = new CloudOffboardingServiceImpl(); + CloudOffboardingParameters parameters = new CloudOffboardingParameters(); + parameters.setEndpointIds(Collections.singletonList(VCU_ENDPOINT_ID_FOR_FORMER_TEST_RUN)); + parameters.setOnboardingResponse(read(Identifier.TELEMETRY_PLATFORM)); + cloudOffboardingService.send(parameters); + FetchMessageService fetchMessageService = new FetchMessageServiceImpl(); + Optional> fetchMessageResponses = + fetchMessageService.fetch( + read(Identifier.TELEMETRY_PLATFORM), + new DefaultCancellationToken(MAX_TRIES_BEFORE_FAILURE, DEFAULT_INTERVAL)); + waitForTheAgrirouterToProcessSingleMessage(); + Assertions.assertTrue(fetchMessageResponses.isPresent()); + Assertions.assertEquals(1, fetchMessageResponses.get().size()); + Assertions.assertNotNull(fetchMessageResponses.get().get(0).getCommand()); + } + @Test + @Disabled( + "Since there are multiple problems with the environment, the test is currently disabled.") void givenValidIdAndNameWhenOnboardingVirtualCuThenTheOnbardingShouldBePossible() throws Throwable { CloudOnboardingService cloudOnboardingService = new CloudOnboardingServiceImpl(); @@ -84,7 +110,7 @@ void givenValidIdAndNameWhenOnboardingVirtualCuThenTheOnbardingShouldBePossible( parameters.setOnboardingResponse(read(Identifier.TELEMETRY_PLATFORM)); cloudOnboardingService.send(parameters); - Thread.sleep(TimeUnit.SECONDS.toMillis(5)); + waitForTheAgrirouterToProcessSingleMessage(); FetchMessageService fetchMessageService = new FetchMessageServiceImpl(); Optional> fetchMessageResponses = diff --git a/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/messaging/rest/SendChunkedMessageTest.java b/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/messaging/rest/SendChunkedMessageTest.java new file mode 100644 index 00000000..0253ed02 --- /dev/null +++ b/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/messaging/rest/SendChunkedMessageTest.java @@ -0,0 +1,130 @@ +package com.dke.data.agrirouter.test.messaging.rest; + +import agrirouter.request.Request; +import com.dke.data.agrirouter.api.cancellation.DefaultCancellationToken; +import com.dke.data.agrirouter.api.dto.encoding.DecodeMessageResponse; +import com.dke.data.agrirouter.api.dto.messaging.FetchMessageResponse; +import com.dke.data.agrirouter.api.dto.onboard.OnboardingResponse; +import com.dke.data.agrirouter.api.enums.ContentMessageType; +import com.dke.data.agrirouter.api.enums.SystemMessageType; +import com.dke.data.agrirouter.api.service.messaging.encoding.DecodeMessageService; +import com.dke.data.agrirouter.api.service.messaging.encoding.EncodeMessageService; +import com.dke.data.agrirouter.api.service.messaging.http.FetchMessageService; +import com.dke.data.agrirouter.api.service.parameters.*; +import com.dke.data.agrirouter.impl.common.MessageIdService; +import com.dke.data.agrirouter.impl.messaging.SequenceNumberService; +import com.dke.data.agrirouter.impl.messaging.encoding.DecodeMessageServiceImpl; +import com.dke.data.agrirouter.impl.messaging.encoding.EncodeMessageServiceImpl; +import com.dke.data.agrirouter.impl.messaging.rest.FetchMessageServiceImpl; +import com.dke.data.agrirouter.impl.messaging.rest.SendMessageServiceImpl; +import com.dke.data.agrirouter.test.AbstractIntegrationTest; +import com.dke.data.agrirouter.test.Assertions; +import com.dke.data.agrirouter.test.OnboardingResponseRepository; +import com.google.protobuf.ByteString; +import java.io.IOException; +import java.util.*; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Stream; +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.http.HttpStatus; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +/** Test case to show the behavior for chunked message sending. */ +class SendChunkedMessageTest extends AbstractIntegrationTest { + + private static final int MAX_CHUNK_SIZE = 1024000; + + @ParameterizedTest + @MethodSource("fakeRawMessageContentThatHasToBeChunked") + void + givenLargeContentMessageWhenSendingTheMessageToTheAgrirouterTheSdkShouldHelpToSendTheFileInMultipleChunks( + ByteString messageContent, int expectedNrOfChunks) + throws IOException, InterruptedException { + + final EncodeMessageService encodeMessageService = new EncodeMessageServiceImpl(); + final SendMessageServiceImpl sendMessageService = new SendMessageServiceImpl(); + final OnboardingResponse onboardingResponse = + OnboardingResponseRepository.read(OnboardingResponseRepository.Identifier.FARMING_SOFTWARE); + + MessageHeaderParameters messageHeaderParameters = new MessageHeaderParameters(); + messageHeaderParameters.setTechnicalMessageType(ContentMessageType.ISO_11783_TASKDATA_ZIP); + messageHeaderParameters.setApplicationMessageId(MessageIdService.generateMessageId()); + messageHeaderParameters.setApplicationMessageSeqNo( + SequenceNumberService.generateSequenceNumberForEndpoint(onboardingResponse)); + messageHeaderParameters.setMode(Request.RequestEnvelope.Mode.PUBLISH); + + PayloadParameters payloadParameters = new PayloadParameters(); + payloadParameters.setValue(messageContent); + payloadParameters.setTypeUrl(SystemMessageType.EMPTY.getKey()); + + List tuples = + encodeMessageService.chunkAndEncode( + messageHeaderParameters, payloadParameters, onboardingResponse); + + tuples.forEach( + messageParameterTuple -> + Assertions.assertTrue( + Objects.requireNonNull(messageParameterTuple.getPayloadParameters().getValue()) + .toStringUtf8() + .length() + <= MAX_CHUNK_SIZE)); + + List encodedMessages = encodeMessageService.encode(tuples); + + SendMessageParameters sendMessageParameters = new SendMessageParameters(); + sendMessageParameters.setEncodedMessages(encodedMessages); + sendMessageParameters.setOnboardingResponse(onboardingResponse); + sendMessageService.send(sendMessageParameters); + + waitForTheAgrirouterToProcessMultipleMessages(); + + FetchMessageService fetchMessageService = new FetchMessageServiceImpl(); + Optional> fetchMessageResponses = + fetchMessageService.fetch( + onboardingResponse, + new DefaultCancellationToken(MAX_TRIES_BEFORE_FAILURE, DEFAULT_INTERVAL)); + + Assertions.assertTrue(fetchMessageResponses.isPresent()); + Assertions.assertEquals(expectedNrOfChunks, fetchMessageResponses.get().size()); + + DecodeMessageService decodeMessageService = new DecodeMessageServiceImpl(); + AtomicReference decodeMessageResponse = new AtomicReference<>(); + fetchMessageResponses.get().stream() + .map(FetchMessageResponse::getCommand) + .forEach( + message -> { + Assertions.assertNotNull(message); + decodeMessageResponse.set(decodeMessageService.decode(message.getMessage())); + + Assertions.assertMatchesAny( + Arrays.asList(HttpStatus.SC_OK, HttpStatus.SC_CREATED, HttpStatus.SC_NO_CONTENT), + decodeMessageResponse.get().getResponseEnvelope().getResponseCode()); + }); + } + + /** + * Delivers fake message content for multiple test cases. + * + * @return - + */ + private static Stream fakeRawMessageContentThatHasToBeChunked() { + return Stream.of( + Arguments.of( + ByteString.copyFromUtf8( + RandomStringUtils.randomAlphabetic( + PayloadParametersKt.MAX_LENGTH_FOR_RAW_MESSAGE_CONTENT * 3)), + 3), + Arguments.of( + ByteString.copyFromUtf8( + RandomStringUtils.randomAlphabetic( + PayloadParametersKt.MAX_LENGTH_FOR_RAW_MESSAGE_CONTENT * 2)), + 2), + Arguments.of( + ByteString.copyFromUtf8( + RandomStringUtils.randomAlphabetic( + PayloadParametersKt.MAX_LENGTH_FOR_RAW_MESSAGE_CONTENT)), + 1)); + } +} diff --git a/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/messaging/rest/SetCapabilityServiceTest.java b/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/messaging/rest/SetCapabilityServiceTest.java index 1c8930b3..befabfee 100644 --- a/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/messaging/rest/SetCapabilityServiceTest.java +++ b/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/messaging/rest/SetCapabilityServiceTest.java @@ -1,7 +1,5 @@ package com.dke.data.agrirouter.test.messaging.rest; -import static com.dke.data.agrirouter.impl.messaging.rest.MessageFetcher.DEFAULT_INTERVAL; -import static com.dke.data.agrirouter.impl.messaging.rest.MessageFetcher.MAX_TRIES_BEFORE_FAILURE; import static com.dke.data.agrirouter.test.OnboardingResponseRepository.Identifier; import static com.dke.data.agrirouter.test.OnboardingResponseRepository.read; @@ -27,7 +25,6 @@ import java.util.Arrays; import java.util.List; import java.util.Optional; -import java.util.concurrent.TimeUnit; import org.apache.http.HttpStatus; import org.junit.jupiter.api.Test; @@ -54,7 +51,7 @@ void givenValidEndpointWhenSendingCapabilitiesTheCapabilityMessageShouldBeAccept parameters.setCapabilitiesParameters(capabilities); setCapabilityService.send(parameters); - Thread.sleep(TimeUnit.SECONDS.toMillis(3)); + waitForTheAgrirouterToProcessSingleMessage(); FetchMessageService fetchMessageService = new FetchMessageServiceImpl(); Optional> fetchMessageResponses = @@ -97,7 +94,7 @@ void givenValidEndpointWhenSendingInvalidCapabilitiesTheCapabilityMessageShouldN parameters.setCapabilitiesParameters(capabilities); setCapabilityService.send(parameters); - Thread.sleep(TimeUnit.SECONDS.toMillis(3)); + waitForTheAgrirouterToProcessSingleMessage(); FetchMessageService fetchMessageService = new FetchMessageServiceImpl(); Optional> fetchMessageResponses = diff --git a/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/messaging/rest/SetSubscriptionServiceTest.java b/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/messaging/rest/SetSubscriptionServiceTest.java index 1dcf5b1f..bba8e7d0 100644 --- a/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/messaging/rest/SetSubscriptionServiceTest.java +++ b/agrirouter-sdk-java-tests/src/test/java/com/dke/data/agrirouter/test/messaging/rest/SetSubscriptionServiceTest.java @@ -1,7 +1,5 @@ package com.dke.data.agrirouter.test.messaging.rest; -import static com.dke.data.agrirouter.impl.messaging.rest.MessageFetcher.DEFAULT_INTERVAL; -import static com.dke.data.agrirouter.impl.messaging.rest.MessageFetcher.MAX_TRIES_BEFORE_FAILURE; import static com.dke.data.agrirouter.test.OnboardingResponseRepository.Identifier; import static com.dke.data.agrirouter.test.OnboardingResponseRepository.read; @@ -26,7 +24,6 @@ import java.util.Arrays; import java.util.List; import java.util.Optional; -import java.util.concurrent.TimeUnit; import org.apache.http.HttpStatus; import org.junit.jupiter.api.Test; @@ -48,7 +45,7 @@ void givenValidEndpointWhenSendingSubscriptionsTheSubscriptionMessageShouldBeAcc parameters.setSubscriptions(subscriptions); setSubscriptionService.send(parameters); - Thread.sleep(TimeUnit.SECONDS.toMillis(3)); + waitForTheAgrirouterToProcessSingleMessage(); FetchMessageService fetchMessageService = new FetchMessageServiceImpl(); Optional> fetchMessageResponses = @@ -86,7 +83,7 @@ void givenValidEndpointWhenSendingInvalidSubscriptionsTheSubscriptionMessageShou parameters.setSubscriptions(subscriptions); setSubscriptionService.send(parameters); - Thread.sleep(TimeUnit.SECONDS.toMillis(3)); + waitForTheAgrirouterToProcessSingleMessage(); FetchMessageService fetchMessageService = new FetchMessageServiceImpl(); Optional> fetchMessageResponses = diff --git a/pom.xml b/pom.xml index 3ae6c65a..19d5e145 100644 --- a/pom.xml +++ b/pom.xml @@ -86,7 +86,7 @@ 2.38.0 1.1.1 1.3.71 - 2.13.3 + 2.16.0 1.2.4 1.14 2.1.1 @@ -100,6 +100,7 @@ 3.0.2 3.1.0 2.9 + 30.1.1-jre @@ -151,6 +152,12 @@ ${junit-jupiter.version} test + + org.junit.jupiter + junit-jupiter-params + ${junit-jupiter.version} + test + org.junit.jupiter junit-jupiter-engine @@ -275,6 +282,13 @@ ${javax.ws.rs-api.version} + + + com.google.guava + guava + ${guava.version} + +