RADAR Push Endpoint that exposes REST interface for push subscription based APIs to the Apache Kafka.
Currently, Garmin is integrated. For adding more services, see the Extending section.
pushIntegration:
# Push service specific config
garmin:
enabled: true
userRepositoryClass: "org.radarbase.push.integration.garmin.user.ServiceUserRepository"
service-n:
enabled: true
property-xyz: "value"
For Garmin, you will need to configure the endpoints in the Garmin Developer Portal
If you are using the org.radarbase.push.integration.garmin.user.GarminServiceUserRepository
make sure to create the oauth client in management portal with following properties -
client_id: your_client_id
client_secret: your_client_secret
grant_type: client_credentials
resources: res_restAuthorizer
scope: "SUBJECT.READ", "MEASUREMENT.READ", "SUBJECT.UPDATE", "MEASUREMENT.CREATE"
then configure the following properties-
pushIntegration:
garmin:
enabled: true
userRepositoryClass: org.radarbase.push.integration.garmin.user.GarminServiceUserRepository
userRepositoryUrl: "http://radar-rest-sources-backend:8090/rest-sources/backend/"
userRepositoryClientId: "your_client_id"
userRepositoryClientSecret: "your_client_secret"
userRepositoryTokenUrl: "http://managementportal-app:8080/oauth/token/"
Modify the URLs according to your deployment.
Properties for Kafka Admin Client and Kafka Producer can be set using environment variables. For this, prefix the
property name with KAFKA_ADMIN_
or KAFKA_PRODUCER_
, respectively, followed by the property name in uppercase and
with dots replaced by underscores. For example, bootstrap.servers
for Kafka Producer should be set as
KAFKA_PRODUCER_BOOTSTRAP_SERVERS
and default.api.timeout.ms
for Kafka Admin Client should be set as
KAFKA_ADMIN_DEFAULT_API_TIMEOUT_MS
.
Start the Service with
docker-compose up -d --build
then once kafka-1
is ready, create topics with
TOPIC=test
docker-compose exec kafka-1 kafka-topics --create --topic $TOPIC --bootstrap-server kafka-1:9092
Now the service is accessible through http://localhost:8090/push/integrations/. Garmin endpoints are available at -
- http://localhost:8090/push/integrations/garmin/dailies
- http://localhost:8090/push/integrations/garmin/activities
- http://localhost:8090/push/integrations/garmin/activityDetails
- http://localhost:8090/push/integrations/garmin/manualActivities
- http://localhost:8090/push/integrations/garmin/epochs
- http://localhost:8090/push/integrations/garmin/sleeps
- http://localhost:8090/push/integrations/garmin/bodyCompositions
- http://localhost:8090/push/integrations/garmin/stress
- http://localhost:8090/push/integrations/garmin/userMetrics
- http://localhost:8090/push/integrations/garmin/moveIQ
- http://localhost:8090/push/integrations/garmin/pulseOx
- http://localhost:8090/push/integrations/garmin/respiration
- http://localhost:8090/push/integrations/garmin/deregister
This section walks through add a new push service integration. These should be implemented in a
new package org.radarbase.push.integration.<service-name>
.
Create a new Resource and configure the endpoints required by the push service integration. For reference take a look at GarminPushEndpoint
Create a new UserRepository to provide user specific info and authorization info. This should implement the interface UserRepository. For reference, take a look at ServiceUserRepository
Create a new AuthValidator to check the requests and authorise with users provided by
the User Repository. This can be done by implementing
the AuthValidator
interface provided by radar-jersey
library.
For reference, take a look
at GarminAuthValidator
This is optional but will help keep the code consistent. Create Converters for converting data posted by the push service to Kafka records. This can be done by implementing the AvroConverter interface. For reference, take a look at converter implementations in garmin converter package.
Firstly, create a Resource Enhancer to register all your required classes to Jersey Context.
Remember to use named
to distinguish your service implementation.
class ServiceXIntegrationResourceEnhancer(private val config: Config) :
JerseyResourceEnhancer {
override fun ResourceConfig.enhance() {
packages(
"org.radarbase.push.integration.servicex.resource",
"org.radarbase.push.integration.servicex.filter"
)
}
override fun AbstractBinder.enhance() {
bind(config.pushIntegration.servicex.userRepository)
.to(UserRepository::class.java)
.named("servicex")
.`in`(Singleton::class.java)
bind(ServiceXAuthValidator::class.java)
.to(AuthValidator::class.java)
.named("servicex")
.`in`(Singleton::class.java)
}
}
Next, add your AuthValidator
to
the DelegatedAuthValidator so
service specific Auth can be performed.
Make sure the path to your service's resources contain the matching string (servicex
in this
case).
...
fun delegate(): AuthValidator {
return when {
uriInfo.matches(GARMIN_QUALIFIER) -> namedValidators.named(GARMIN_QUALIFIER).get()
uriInfo.matches("servicex") -> namedValidators.named("servicex").get()
// Add support for more as integrations are added
else -> throw IllegalStateException()
}
}
...
Next, add the configuration to the Config class.
...
data class PushIntegrationConfig(
val garmin: GarminConfig = GarminConfig(),
val servicex: ServiceXConfig
)
data class ServiceXConfig(
val enabled: Boolean = false,
val userRepositoryClass: String,
val property1: String,
val property2: List<String>
)
...
Finally, add your newly created Resource Enhancer to PushIntegrationEnhancerFactory
...
// Push Service specific enhancers
if (config.pushIntegration.garmin.enabled) {
enhancersList.add(GarminPushIntegrationResourceEnhancer(config))
}
if (config.pushIntegration.servicex.enabled) {
enhancersList.add(ServiceXIntegrationResourceEnhancer(config))
}
...