Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change serialization strategy #123

Merged
merged 11 commits into from
Sep 2, 2024
2 changes: 1 addition & 1 deletion keycloak-theme/vite.config.ts
davidscavnicky marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export default defineConfig({
/*
* Uncomment this if you want to use the default domain provided by GitHub Pages
* replace "keycloakify-starter" with your repository name.
* This is only relevent if you are building an Wep App + A Keycloak theme.
* This is only relevant if you are building an Wep App + A Keycloak theme.
* If you are only building a Keycloak theme, you can ignore this.
*/
//base: "/keycloakify-starter/"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package dk.cachet.carp.webservices.common.serialisers

import dk.cachet.carp.common.application.services.ApplicationService
import dk.cachet.carp.common.infrastructure.services.ApplicationServiceRequest
import dk.cachet.carp.webservices.common.input.WS_JSON
import kotlinx.serialization.KSerializer

/**
* Serializes and deserializes requests to and from the application service.
* This is used to serialize requests to the application service and deserialize responses from the application service.
*
* @param TRequest The type of request which can be serialized and deserialized.
*/
abstract class ApplicationRequestSerializer<TRequest : ApplicationServiceRequest<*, *>> {
companion object {
val json = WS_JSON
}

/**
* Deserialize the request from the specified [content].
*
* @param serializer The serializer to use to deserialize the request.
* @param content The content to deserialize from.
* @return The deserialized request object.
*/
fun <TRequest> deserializeRequest(
serializer: KSerializer<TRequest>,
content: String,
): TRequest {
return json.decodeFromString(serializer, content)
}

/**
* Serialize the specified [request] to a string.
*
* @param request The request body to serialize.
* @param content The content to serialize.
* @return The serialized request string.
*/
abstract fun <TService : ApplicationService<TService, *>> serializeResponse(
request: ApplicationServiceRequest<TService, *>,
content: Any?,
): Any?
}
Original file line number Diff line number Diff line change
@@ -1,47 +1,26 @@
package dk.cachet.carp.webservices.common.serialisers

import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.databind.JsonSerializer
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.databind.SerializerProvider
import com.fasterxml.jackson.databind.module.SimpleModule
import com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer
import com.fasterxml.jackson.datatype.jsr310.ser.InstantSerializer
import com.fasterxml.jackson.module.kotlin.KotlinModule
import dk.cachet.carp.common.application.UUID
import dk.cachet.carp.common.application.devices.DeviceRegistration
import dk.cachet.carp.common.application.users.AccountIdentity
import dk.cachet.carp.data.application.DataStreamBatch
import dk.cachet.carp.data.application.DataStreamsConfiguration
import dk.cachet.carp.data.application.Measurement
import dk.cachet.carp.data.application.SyncPoint
import dk.cachet.carp.data.infrastructure.DataStreamServiceRequest
import dk.cachet.carp.deployments.application.PrimaryDeviceDeployment
import dk.cachet.carp.deployments.application.StudyDeploymentStatus
import dk.cachet.carp.deployments.application.users.ActiveParticipationInvitation
import dk.cachet.carp.deployments.application.users.ParticipantData
import dk.cachet.carp.deployments.domain.StudyDeploymentSnapshot
import dk.cachet.carp.deployments.domain.users.ParticipantGroupSnapshot
import dk.cachet.carp.deployments.infrastructure.DeploymentServiceRequest
import dk.cachet.carp.deployments.infrastructure.ParticipationServiceRequest
import dk.cachet.carp.protocols.application.ProtocolVersion
import dk.cachet.carp.protocols.application.StudyProtocolSnapshot
import dk.cachet.carp.protocols.infrastructure.ProtocolFactoryServiceRequest
import dk.cachet.carp.protocols.infrastructure.ProtocolServiceRequest
import dk.cachet.carp.studies.application.StudyDetails
import dk.cachet.carp.studies.application.StudyStatus
import dk.cachet.carp.studies.application.users.ParticipantGroupStatus
import dk.cachet.carp.studies.domain.StudySnapshot
import dk.cachet.carp.studies.domain.users.RecruitmentSnapshot
import dk.cachet.carp.studies.infrastructure.RecruitmentServiceRequest
import dk.cachet.carp.studies.infrastructure.StudyServiceRequest
import dk.cachet.carp.webservices.account.serdes.AccountIdentityDeserializer
import dk.cachet.carp.webservices.account.serdes.AccountIdentitySerializer
import dk.cachet.carp.webservices.common.configuration.internationalisation.service.MessageBase
import dk.cachet.carp.webservices.common.serialisers.serdes.UUIDDeserializer
import dk.cachet.carp.webservices.common.serialisers.serdes.UUIDSerializer
import dk.cachet.carp.webservices.datastream.serdes.*
import dk.cachet.carp.webservices.deployment.serdes.*
import dk.cachet.carp.webservices.protocol.serdes.*
import dk.cachet.carp.webservices.study.serdes.*
import kotlinx.datetime.Instant
import kotlinx.datetime.toJavaInstant
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Primary
Expand All @@ -56,135 +35,39 @@ import org.springframework.context.annotation.Primary
class ObjectMapperConfig(validationMessages: MessageBase) : SimpleModule() {
init
{
// Study
this.addSerializer(StudyServiceRequest::class.java, StudyServiceRequestSerializer(validationMessages))
this.addDeserializer(StudyServiceRequest::class.java, StudyServiceRequestDeserializer(validationMessages))
// Protocol
this.addSerializer(ProtocolServiceRequest::class.java, ProtocolServiceRequestSerializer(validationMessages))
this.addDeserializer(ProtocolServiceRequest::class.java, ProtocolServiceRequestDeserializer(validationMessages))
// StudyProtocolSnapshot
this.addSerializer(StudyProtocolSnapshot::class.java, StudyProtocolSnapshotSerializer(validationMessages))
this.addDeserializer(StudyProtocolSnapshot::class.java, StudyProtocolSnapshotDeserializer(validationMessages))
// DeviceRegistration
this.addSerializer(DeviceRegistration::class.java, DeviceRegistrationSerializer(validationMessages))
this.addDeserializer(DeviceRegistration::class.java, DeviceRegistrationDeserializer(validationMessages))
// Deployment
this.addSerializer(DeploymentServiceRequest::class.java, DeploymentServiceRequestSerializer(validationMessages))
this.addDeserializer(
DeploymentServiceRequest::class.java,
DeploymentServiceRequestDeserializer(validationMessages),
)
// StudyDeploymentSnapshot
this.addSerializer(StudyDeploymentSnapshot::class.java, StudyDeploymentSnapshotSerializer(validationMessages))
this.addDeserializer(
StudyDeploymentSnapshot::class.java,
StudyDeploymentSnapshotDeserializer(validationMessages),
)
// StudyDeploymentStatus
this.addSerializer(StudyDeploymentStatus::class.java, StudyDeploymentStatusSerializer(validationMessages))
this.addDeserializer(StudyDeploymentStatus::class.java, StudyDeploymentStatusDeserializer(validationMessages))
// MasterDeviceDeployment
this.addSerializer(PrimaryDeviceDeployment::class.java, PrimaryDeviceDeploymentSerializer(validationMessages))
this.addDeserializer(
PrimaryDeviceDeployment::class.java,
MasterDeviceDeploymentDeserializer(validationMessages),
)
// AccountIdentity
this.addSerializer(AccountIdentity::class.java, AccountIdentitySerializer(validationMessages))
this.addDeserializer(AccountIdentity::class.java, AccountIdentityDeserializer(validationMessages))
// StudyStatus
this.addSerializer(StudyStatus::class.java, StudyStatusSerializer(validationMessages))
this.addDeserializer(StudyStatus::class.java, StudyStatusDeserializer(validationMessages))
// StudySnapshot
this.addSerializer(StudySnapshot::class.java, StudySnapshotSerializer(validationMessages))
this.addDeserializer(StudySnapshot::class.java, StudySnapshotDeserializer(validationMessages))
// UUID
this.addSerializer(UUID::class.java, UUIDSerializer(validationMessages))
this.addDeserializer(UUID::class.java, UUIDDeserializer(validationMessages))
// StudyDetails
this.addSerializer(StudyDetails::class.java, StudyDetailsSerializer(validationMessages))
this.addDeserializer(StudyDetails::class.java, StudyDetailsDeserializer(validationMessages))
// ParticipantGroupStatus
this.addSerializer(ParticipantGroupStatus::class.java, ParticipantGroupStatusSerializer(validationMessages))
this.addDeserializer(
ParticipantGroupStatus::class.java,
ParticipantGroupStatusDeserializer(validationMessages),
)
// ProtocolFactoryServiceRequest
this.addSerializer(
ProtocolFactoryServiceRequest::class.java,
ProtocolFactoryServiceSerializer(validationMessages),
)
this.addDeserializer(
ProtocolFactoryServiceRequest::class.java,
ProtocolFactoryServiceDeserializer(validationMessages),
)
// ParticipationServiceRequest
this.addSerializer(
ParticipationServiceRequest::class.java,
ParticipationServiceRequestSerializer(validationMessages),
)
this.addDeserializer(
ParticipationServiceRequest::class.java,
ParticipationServiceRequestDeserializer(validationMessages),
)
// ParticipantGroupSnapshot
this.addSerializer(ParticipantGroupSnapshot::class.java, ParticipantGroupSnapshotSerializer(validationMessages))
this.addDeserializer(
ParticipantGroupSnapshot::class.java,
ParticipantGroupSnapshotDeserializer(validationMessages),
)
// Participant Data
this.addSerializer(ParticipantData::class.java, ParticipantDataSerializer(validationMessages))
this.addDeserializer(ParticipantData::class.java, ParticipantDataDeserializer(validationMessages))
// Recruitment Snapshot
this.addSerializer(RecruitmentSnapshot::class.java, RecruitmentSnapshotSerializer(validationMessages))
this.addDeserializer(RecruitmentSnapshot::class.java, RecruitmentSnapshotDeserializer(validationMessages))
// DataStreamConfiguration
this.addSerializer(DataStreamsConfiguration::class.java, DataStreamsConfigurationSerializer(validationMessages))
this.addDeserializer(
DataStreamsConfiguration::class.java,
DataStreamsConfigurationDeserializer(validationMessages),
)
// RecruitmentServiceRequest
this.addSerializer(
RecruitmentServiceRequest::class.java,
RecruitmentServiceRequestSerializer(validationMessages),
)
this.addDeserializer(
RecruitmentServiceRequest::class.java,
RecruitmentServiceRequestDeserializer(validationMessages),
)
// ProtocolVersion
this.addSerializer(ProtocolVersion::class.java, ProtocolVersionSerializer(validationMessages))
this.addDeserializer(ProtocolVersion::class.java, ProtocolVersionDeserializer(validationMessages))
// DataStream
this.addSerializer(DataStreamServiceRequest::class.java, DataStreamServiceRequestSerializer(validationMessages))
this.addDeserializer(
DataStreamServiceRequest::class.java,
DataStreamServiceRequestDeserializer(validationMessages),
)

// SyncPoint
this.addSerializer(SyncPoint::class.java, SyncPointSerializer(validationMessages))
this.addDeserializer(SyncPoint::class.java, SyncPointDeserializer(validationMessages))
// Measurement
this.addSerializer(Measurement::class.java, MeasurementSerializer(validationMessages))
this.addDeserializer(Measurement::class.java, MeasurementDeserializer(validationMessages))
// Act
this.addSerializer(
ActiveParticipationInvitation::class.java,
ActiveParticipationInvitationSerializer(validationMessages),
)
this.addDeserializer(
ActiveParticipationInvitation::class.java,
ActiveParticipationInvitationDeserializer(validationMessages),
)

// DataStreamBatch
this.addSerializer(DataStreamBatch::class.java, DataStreamBatchSerializer(validationMessages))
this.addDeserializer(DataStreamBatch::class.java, DataStreamBatchDeserializer(validationMessages))

this.addSerializer(java.time.Instant::class.java, InstantSerializer.INSTANCE)
this.addDeserializer(java.time.Instant::class.java, InstantDeserializer.INSTANT)
this.addSerializer(Instant::class.java, KInstantSerializer.INSTANCE)
}

class KInstantSerializer : JsonSerializer<Instant>() {
override fun serialize(
value: Instant,
gen: JsonGenerator,
serializers: SerializerProvider,
) {
return(InstantSerializer.INSTANCE.serialize(value.toJavaInstant(), gen, serializers))
}

companion object {
val INSTANCE = KInstantSerializer()
}
}

/**
Expand Down

This file was deleted.

This file was deleted.

davidscavnicky marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class DataStreamController(
) {
companion object {
private val LOGGER: Logger = LogManager.getLogger()
private val serializer = DataStreamRequestSerializer()

/** Endpoint URI constants */
const val DATA_STREAM_SERVICE = "/api/data-stream-service"
Expand All @@ -29,10 +30,12 @@ class DataStreamController(
@PostMapping(value = [DATA_STREAM_SERVICE])
@Operation(tags = ["dataStream/request.json"])
suspend fun invoke(
@RequestBody request: DataStreamServiceRequest<*>,
@RequestBody httpMessage: String,
): ResponseEntity<Any> {
val request = WS_JSON.decodeFromString(DataStreamServiceRequest.Serializer, httpMessage)
LOGGER.info("Start POST: $DATA_STREAM_SERVICE -> ${ request::class.simpleName }")
return dataStreamService.core.invoke(request).let { ResponseEntity.ok(it) }
val ret = dataStreamService.core.invoke(request)
return serializer.serializeResponse(request, ret).let { ResponseEntity.ok(it) }
}

@PostMapping(value = [DATA_STREAM_SERVICE_GZIP])
Expand Down
Loading
Loading