GraphQL Foundation — Dependencies, Schema, and Configuration#15
Open
devin-ai-integration[bot] wants to merge 5 commits intodevelop-7.0.xfrom
Open
GraphQL Foundation — Dependencies, Schema, and Configuration#15devin-ai-integration[bot] wants to merge 5 commits intodevelop-7.0.xfrom
devin-ai-integration[bot] wants to merge 5 commits intodevelop-7.0.xfrom
Conversation
- Add spring-boot-starter-graphql and graphql-java-extended-scalars to root pom dependencyManagement, wired into broadleaf-framework-web - Exclude transitive graphql-java from extended-scalars to align with the graphql-java version managed by spring-boot-starter-graphql - Pin reactive-streams to 1.0.4 to satisfy dependency convergence - Add GraphQL schema under core/broadleaf-framework-web/src/main/resources/graphql covering catalog, cart, checkout, and account types, queries and mutations - Add GraphQLContextInterceptor that populates CustomerState and CartState - Add GraphQLExceptionResolver mapping Broadleaf domain exceptions to structured GraphQL errors with stable code extensions - Add GraphQLConfig registering BigDecimal scalar aliased to GraphQLFloat - Add graphql-config.properties enabling GraphiQL and the /graphql endpoint
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
- Use NumberUtils.isDigits instead of isCreatable to avoid NumberFormatException on inputs like hex, decimal, scientific, or type-qualified strings that isCreatable accepts but Long.valueOf cannot parse. - Move GraphQL endpoint defaults into the module's existing config/bc/web/common.properties so they are loaded by Broadleaf's FrameworkCommonClasspathPropertySource. Remove the classpath-root graphql-config.properties, which was never picked up by Spring Boot or Broadleaf's environment configurer.
Some Broadleaf exceptions (e.g. PricingException, AddToCartException) have no-arg constructors that leave the message null. GraphqlErrorBuilder.build() asserts message is non-null and would otherwise throw, preventing the structured error from being returned. Fall back to the exception's simple class name when no message is present.
…ecision Aliasing BigDecimal to GraphQLFloat silently degrades values to IEEE 754 doubles, which can corrupt large monetary amounts that Broadleaf's Money type stores as java.math.BigDecimal specifically to preserve exact decimal precision. Register the schema's BigDecimal scalar using ExtendedScalars.GraphQLBigDecimal, which serializes with full precision.
…omer ids isDigits returns true for all-digit strings that overflow Long.MAX_VALUE (e.g. a very long numeric header supplied by a malicious client), which Long.valueOf then rejects with NumberFormatException, failing the entire GraphQL request. Wrap the parse in a helper that returns null on overflow and falls through to the anonymous-customer path.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
Introduces the foundational GraphQL layer in
broadleaf-framework-web: thespring-boot-starter-graphqldependency, a first-pass schema covering catalog / cart / checkout / account, a context interceptor that populatesCustomerStateandCartStatefor each request, and a resolver that maps Broadleaf domain exceptions to structured GraphQL errors. No data fetchers are wired up yet — that lands in follow-up tickets.Changes
Dependencies (root
pom.xml)spring-graphql.version=1.3.4,graphql-java-extended-scalars.version=22.0.spring-boot-starter-graphqlandgraphql-java-extended-scalarsto<dependencyManagement>.graphql-javais excluded from the transitive graph ofgraphql-java-extended-scalarsso the version shipped byspring-boot-starter-graphqlwins (otherwise the enforcer plugin'sDependencyConvergencerule fails: extended-scalars 22.0 pulls graphql-java 22.0, while spring-graphql 1.4.5 pulls 24.3).org.reactivestreams:reactive-streams:1.0.4to resolve a separate convergence conflict betweenjava-dataloader(1.0.3) andreactor-core(1.0.4).core/broadleaf-framework-web/pom.xmlspring-boot-starter-graphqlandgraphql-java-extended-scalarsto the module.Schema —
core/broadleaf-framework-web/src/main/resources/graphql/schema.graphqlsQuery: catalog (product, category, sku, search), cart/orders, account.Mutation: cart ops, promo codes, checkout save/process, account/address management.Product,Category,Sku,Money,Order,OrderItem,FulfillmentGroup,FulfillmentGroupItem,FulfillmentOption,OrderPayment,OfferCode,Customer,CustomerAddress,Address,ProductOption,ProductOptionValue,PromoCodeResult,CheckoutResult.OrderStatus, customBigDecimalscalar, and input types for mutations.GraphQLContextInterceptor(implementsWebGraphQlInterceptor)RestApiCustomerStateFilter).CustomerState; otherwise creates an anonymous customer.CartStateviaOrderService.findCartForCustomer.blRuleMaprequest attribute for content rule processing.GraphQLExceptionResolver(extendsDataFetcherExceptionResolverAdapter)AddToCartException,RemoveFromCartException,UpdateCartException,IllegalCartOperationException,OfferMaxUseExceededException,CheckoutException→ValidationErrorwith distinctcodeextensions.PricingException→DataFetchingExceptionwithcode=PRICING_ERROR.getMessage()isnull, since several Broadleaf exceptions have no-arg constructors andGraphqlErrorBuilderasserts a non-null message.GraphQLConfigRuntimeWiringConfigurerbean that binds the schema'sBigDecimalscalar toExtendedScalars.GraphQLBigDecimal. This preserves fulljava.math.BigDecimalprecision for monetary amounts; aliasing toGraphQLFloat(as originally drafted) would have silently degraded values to IEEE 754 doubles.GraphQL endpoint defaults — merged into
core/broadleaf-framework-web/src/main/resources/config/bc/web/common.propertiesso they flow through Broadleaf'sFrameworkCommonClasspathPropertySource:spring.graphql.graphiql.enabled=true,spring.graphql.path=/graphql,spring.graphql.schema.locations=classpath:graphql/.Updates Since Last Revision
NumberUtils.isCreatablewithisDigitsand wrappedLong.valueOfin aparseCustomerIdhelper that returnsnullonNumberFormatException. This handles both non-decimal inputs accepted byisCreatable(hex, scientific, type-qualified) and all-digit strings that overflowLong.MAX_VALUE, falling through to the anonymous-customer path instead of failing the request.graphql-config.properties(which was never loaded by Spring Boot or Broadleaf'sBroadleafEnvironmentConfigurer) into the module's existingconfig/bc/web/common.properties, sospring.graphql.graphiql.enabledetc. actually take effect.BigDecimalscalar wiring from an alias-to-Float toExtendedScalars.GraphQLBigDecimalto preserve monetary precision.GraphQLExceptionResolver.Build Verification
mvn compile -pl core/broadleaf-framework-web -am -DskipTests— BUILD SUCCESS. No tests added in this ticket.Reviewer Focus / Known Caveats
spring-graphql.versionproperty is declared but unused. Spring Boot 3.5.13 managesspring-graphqlto 1.4.5 transitively, so the1.3.4property has no effect on the resolved version. Happy to either drop the property or override the spring-graphql version explicitly — please advise on preference.ServletWebGraphQlRequestcast. The ticket describes castingWebGraphQlRequesttoServletGraphQlRequest/ServletWebGraphQlRequest, but that class does not exist in spring-graphql 1.4.x. The interceptor instead pulls theHttpServletRequestviaRequestContextHolder'sServletRequestAttributes. This works on the servlet thread (default for spring-graphql webmvc) but would returnnullif a future resolver switches to async/off-thread execution.CustomerState/CartStatevs. reactive pipeline. The interceptor sets thread-local state inintercept()before returningchain.next(...). On the default webmvc path this is fine, but any downstream operator that switches schedulers (e.g.publishOn) would observe empty thread-locals in the data fetcher. If the follow-up data-fetcher ticket uses async/reactive resolvers, we'll likely need to propagate these viaGraphQLContextinstead.graphql-java-extended-scalars:22.0vsgraphql-java:24.3. The exclusion makes the build pass, but extended-scalars 22.0 was compiled against graphql-java 22.x.GraphQLBigDecimalis a stable scalar definition, so this is low-risk in practice, but broader use of extended scalars may eventually require a newer version.@Controller/@SchemaMappingwiring yet — that's scoped to follow-up tickets.Labels & Milestone
Feature, Status:ready-for-code-review7.0.xreleaseLink to Devin session: https://app.devin.ai/sessions/f77499f81dc14942be8dc0a2ac0f41ef
Requested by: @Colhodm