Refactor/api consistency and rename#19
Conversation
services Signed-off-by: jimmy-guzman <hi@jimmy.codes>
Signed-off-by: jimmy-guzman <hi@jimmy.codes>
Signed-off-by: jimmy-guzman <hi@jimmy.codes>
Signed-off-by: jimmy-guzman <hi@jimmy.codes>
Signed-off-by: jimmy-guzman <hi@jimmy.codes>
GlobalExceptionHandler in both services Signed-off-by: jimmy-guzman <hi@jimmy.codes>
Signed-off-by: jimmy-guzman <hi@jimmy.codes>
product-api Behaviors Signed-off-by: jimmy-guzman <hi@jimmy.codes>
REST-idiomatic paths Signed-off-by: jimmy-guzman <hi@jimmy.codes>
|
Signed-off-by: jimmy-guzman <hi@jimmy.codes>
e514f8d to
26dfa53
Compare
| @@ -6,8 +6,6 @@ spring: | |||
|
|
|||
| server: | |||
| port: 8080 | |||
| servlet: | |||
| context-path: /retail_data_services/v1/ | |||
There was a problem hiding this comment.
I understand the intent — service identity belongs in the hostname, not the path. That's a sound principle in a proper service mesh. However, in this repo's context (local dev, docker-compose, case study exercises), multiple services will likely share a single host. Both product-api and cart-service are now rooted at /v1, which creates ambiguity and potential routing conflicts without a differentiating prefix.
I'd suggest restoring a products prefix — either via context-path: /products in application.yml or a top-level @RequestMapping("/products/v1") on the controllers. This keeps the version visible in code while making the routes unambiguous and more self-documenting for learners reading a URL in a tutorial.
Use the same pattern for both /carts and /products - context-path or @RequestMapping.
There was a problem hiding this comment.
Yeah I debated this as well, i'll go with
- /products/v1 and /cart/v1 as
@RequestMappingrather than context-path so Swagger/api-docs/actuator stays at root
| @@ -26,8 +24,6 @@ springdoc: | |||
| path: api-docs | |||
| swagger-ui: | |||
| enabled: true | |||
| config-url: /retail_data_services/v1/api-docs/swagger-config | |||
| url: /retail_data_services/v1/api-docs | |||
There was a problem hiding this comment.
Just want to confirm swagger ui still works w/o these config values.
There was a problem hiding this comment.
They do but will need brought back when #19 (comment) is addressed
Standardize API contracts & rename
Summary
Aligns the two services around consistent naming, REST-idiomatic paths, and uniform error handling. The catalog service is renamed from
retail-data-servicestoproduct-api. Field names, identifiers, and types now match across the service boundary, so cart-service and product-api agree on the wire format.The work splits into nine commits. Commits 1 through 8 land while the directory is still
retail-data-servicesto keep each change reviewable. Commit 9 is the atomic rename that touches all structural identifiers at once.Why
retail-data-serviceswas published while this repo was private, so its image is still private. The repo is public now and both images need to be public. That means republishing either way, so the rename and contract fixes go in the same change rather than locking in the old name on a fresh public artifact.The two services developed independently and never aligned.
tcin,product_id, anditem_idall referred to the same product identifier with no boundary rule. Image and price fields used different names on each side of the call.merch_classwas anIntegerupstream and aStringin cart. Error handling threw bareRuntimeExceptionand leaned onOptional.empty()to produce 404s. The service name said nothing about its domain.Changes
Rename
retail-data-servicestoproduct-api. Directory, Gradle subproject, Java package root (com.target.retail.data.servicestocom.target.retail.product), JAR artifact, Docker service name (datatoproduct-api), OpenAPI title and description, and the spec filename all move.REST-idiomatic paths. Service names leave the URL path and live in the hostname. Version moves into
@RequestMapping("/v1")on the controllers so it shows up in code and Swagger./retail_data_services/v1/items/{id}becomes/v1/items/{id}./cart/v1/cartsbecomes/v1/carts. Product-api config drops thecontext-path.Field name alignment. The frontend case studies call cart, so cart's names are the ones that surface in those exercises. Upstream adopts cart's shorter names rather than the other way around. Image fields become
primaryandalternate. Price fields becomeregularandsale.Identifier standardization.
tcinandproduct_idbecomeitem_ideverywhere: models, DTOs, path variables, CSV headers, service methods, and client URIs.merch_classtype fix. Cart-service stops casting the upstreamIntegertoStringand carries it asIntegerend to end.next_pagesentinel.PaginatedResponse.calculateNextPagereturned0when no further pages existed, which collides with a valid page number. It now returnsnull.Typed exceptions. Both services get domain exceptions (
ItemNotFoundException,PriceNotFoundException,AvailabilityNotFoundExceptionupstream;CartNotFoundException,CartLineItemNotFoundExceptionin cart;InducedFailureExceptionin both) and aGlobalExceptionHandlerthat maps them to consistent status codes with a sharedErrorResponseshape. This drops the pre-check guard pattern inCartControllerand theCustomErrorControllerin product-api.Smaller fixes.
AddItemRequestgets@JsonNaming(SnakeCaseStrategy)to matchUpdateItemRequest. Product-apiBehaviorsswitches fromMap<String, InducedBehavior>with.name()lookups to a type-safeMap<BehaviorType, InducedBehavior>.Error response shape