Product Availability Enrichment
Author:
Fluent Commerce
Changed on:
20 Feb 2024
Key Points
- You would first need to have access to a Fluent account, and have container running.
`localstack`
- There are two possible cache configurations: In-memory cache or External cache.
Prerequisites
Steps
Overview
In this sample project, we will go through some basic features of the Connect SDK by creating a fulfillment options API that can enrich the response from Fluent Platform.
These are the topics covered by this guide:
- Creating a transformation step
- Define cache configuration to improve the performance of product availability calls
- In-memory cache
- External cache
- Cacheable sample
Prerequisites
- localstack container is running
- You have access to a Fluent account
There is a script
`localstack-setup.sh`
It is best to do the following:
First, run this command to open a session with the localstack container
1docker exec -it localstack /bin/bash
Language: java
Name: Command
Description:
[Warning: empty required content area]Then use the commands below to create the secrets, but ensure to update the variables: $ACCOUNT, $RETAILER, $USERNAME, $PASSWORD and $REGION. Regions values are: sydney, dublin, singapore or north_america.
1docker exec -d localstack awslocal secretsmanager create-secret --name fc/connect/product-availability-enrichment/api/fluent/activeAccounts --secret-string "{\"accounts\":[{\"name\":\"$ACCOUNT\", \"region\":\"$REGION\", \"retailers\":[$RETAILER]}]}" ;
2docker exec -d localstack awslocal secretsmanager create-secret --name fc/connect/product-availability-enrichment/$ACCOUNT/api/fluent-account/$RETAILER --secret-string "{\"retailer\":\"1\", \"userName\":\"$USERNAME\", \"password\":\"$PASSWORD\"}";
3docker exec -d localstack awslocal secretsmanager create-secret --name fc/connect/product-availability-enrichment/$ACCOUNT/api/fluent-account/api-keys --secret-string "{\"api-keys\": [{\"retailer\": \"$RETAILER\",\"username\": \"$USERNAME\",\"password\": \"$PASSWORD\",\"keys\": [{\"key\":\"$API_KEY\",\"expiry\":\"$EXPIRY\"}]}]}";
Language: java
Name: Commands
Description:
[Warning: empty required content area]Use ctrl + D to exit the localstack session.
Define transformation step
By using the anotation
`@FulfilmentOptionTransformationStep`
1@Component
2@Slf4j
3@FulfilmentOptionTransformationStep(id = "<transformation-name>", priority = 1)
4public class PickupLocationTransformation implements FulfilmentOptionTransformationChain<FulfilmentRequest, FulfilmentResponse> {
5
6 @Override
7 public FulfilmentResponse transform(final FulfilmentRequest request, final FulfilmentResponse response, final FluentContext context) {
8 //@todo: implement logic here
9 }
10}
Language: java
Name: Example
Description:
[Warning: empty required content area]Define cache configuration to improve the performance of product availability calls
In-memory cache
The Connect-sdk employs Caffeine-cache as its default cache provider. In addition to the default cache keys of connect-sdk, partners can define their own cache keys with custom configuration. This can be achieved by specifying:
- : cache-names
`name`
- : time-to-live of cache key
`expiry-in-seconds`
- : capacity of the cache
`max-size`
1 cache:
2 caffeine:
3 - name: location
4 expiry-in-seconds: 300
5 max-size: 10000
Language: java
Name: Custom configuration
Description:
[Warning: empty required content area]External cache
If partners want to integrate with the other kinds of Cache Providers please refer to Spring-cache solution: IO
For example, to define a new Cache Manager using Redis Cache:
1public class RedisCacheConfiguration {
2
3 public static final String CUSTOM_CACHE_MANAGER = "custom-cache-manager";
4 public static final String LOCATION_CACHE = "location";
5
6 @Value("${fluent-connect.fulfilment-option.location-cache-ttl-seconds:300}")
7 private Duration LOCATION_TTL_SECONDS = 300;
8
9 @Bean
10 @Primary
11 public CacheManager cacheManager(RedisTemplate<String, Object> template) {
12 RedisCacheManager redisCacheManager =
13 RedisCacheManager.RedisCacheManagerBuilder
14 .fromConnectionFactory(template.getConnectionFactory())
15 .cacheDefaults(getCacheConfigurationWithTtl(template, duration))
16 .withCacheConfiguration(LOCATION_CACHE, getCacheConfigurationWithTtl(template, LOCATION_TTL_SECONDS))
17// .withCacheConfiguration("other-cache", getCacheConfigurationWithTtl(template, secondDuration))
18 .transactionAware()
19 .build();
20 return redisCacheManager;
21 }
22
23 private RedisCacheConfiguration getCacheConfigurationWithTtl(
24 RedisTemplate<String, Object> template, Duration duration) {
25
26 return RedisCacheConfiguration
27 .defaultCacheConfig()
28 .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(
29 template.getStringSerializer()))
30 .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(
31 template.getValueSerializer()))
32 .disableCachingNullValues()
33 .entryTtl(duration);
34 }
35
36}
Language: java
Name: Example
Description:
[Warning: empty required content area]Cacheable sample:
1public class LocationService {
2
3 @Cacheable(cacheManager = SDK_CACHE_MANAGER, cacheNames = LOCATION_CACHE, key = "#ref")
4 //@Cacheable(cacheManager = CUSTOM_CACHE_MANAGER, cacheNames = LOCATION_CACHE, key = "#ref")
5 public Optional<GetLocationQuery.Location> getLocation(@NotNull final FluentContext context, @NotNull final String ref) {
6 final GetLocationQuery query = GetLocationQuery.builder().ref(ref).build();
7 final GetLocationQuery.Data locationData = context.executeQuery(query, GetLocationQuery.Data.class);
8 if (locationData != null) {
9 return Optional.ofNullable(locationData.location());
10 }
11 return Optional.empty();
12 }
13
14}
Language: java
Name: Example
Description:
[Warning: empty required content area]Get Fulfilment Option
Beside default fulfilment-options’s response, there are 2 extra attributes: pickupLocationAddress & pickupLocationOpeningTime
1curl --location --request POST 'http://localhost:8080/api/v1/fluent-connect/fulfilment-option' \
2--header 'Authorization: ApiKey 1234567890123456' \
3--header 'fluent.account: CNCTDEV' \
4--header 'Content-Type: application/json' \
5--header 'Cookie: JSESSIONID=B1AD8588367D0E2BD9E63340119E2B46' \
6--data-raw '{
7 "ref": "9c546d29-89a8-48b4-8d6b-fd7b0e2a2497",
8 "retailerId": "67",
9 "type": "CC",
10 "orderType": "CC",
11 "address": {
12 "longitude": 144.969574,
13 "latitude": -37.812104
14 },
15 "products": [
16 {
17 "requestedQuantity": 1,
18 "productRef": "P041122174751_1",
19 "catalogueRef": "PC:MASTER:67"
20 }
21 ]
22}
Language: java
Name: Example:
Description:
[Warning: empty required content area]