Commerce Integration Framework Extensibility via GraphQL

Learn how to extend Commerce core components using GraphQL.

Continue the conversation in Experience League Communities.

Transcript
All right, then let’s start. So welcome to the session on CIF extensibility via CraftQL. My name is Marc Becker. I’m software engineer at Adobe in Basel and mainly working on AM commerce and CIF. So as a quick introduction, so in this talk, I will discuss the extensibility of the CIF core components. Yesterday in the conference, there was a talk about content and commerce on AM as a cloud service by Marcus. And if you haven’t seen this one yet, I highly recommend you do it. You will actually need it like the whole development setup if you want to try out what I’m going to show you today. So the commerce core components are basically part of the AM components library, same like the WCM core components. The goal is to reduce the need for custom code and help accelerate time to market with your AM storefront. And of course, they can easily be extended as you will see today. In the core components, we have both server-side AM-HDL components as well as client-side React components. But today I will specifically talk about the server-side components. The components are open source and available on GitHub. And I put the link on the slide here. So feel free to give them a try. Besides the CF core components, we also provide an AM version of the Venya reference storefront by Magento. It’s an example of how a typical B2C customer experience built with the CF core components and the AM project type archetype can look like. Same like the components, it’s also open source available on GitHub. You find the link here on the slide. And additionally, we have an out-of-the-box working content package, which is available for you to install on your AM instance to try it out directly. Okay, so about customization of the CF core components. I want to talk about three different ways of customizing and extending the CF core components today. So first I will talk about sling model delegation with retrievers, which you can use to customize existing CF core components. And for use cases where you want to build your own components, I will show you how to use the GraphQL client that comes with CF. And for use cases where you want to customize your GraphQL endpoint or to integrate with third-party commerce, we provide a GraphQL integration layer, which I will show you. All right. So before we jump into the first pattern, let me quickly explain when you want to use this. In general, we recommend to, whenever possible, use an existing CF core component as a starting point for your customization. So in particular, if you want to extend the GraphQL query of a component, for example, to retrieve additional custom product attributes, this is the pattern you want to use. Also for CF in general, we use the Magento GraphQL schema as main API for communicating between AM and the commerce provider. And to make the life of component developers easier, we actually use a generator project to generate Java classes from the Magento GraphQL schema and use those classes in our components. To make this work, we leverage the GraphQL introspection feature. So on the right side here on the slide, you can see an example how you would write a GraphQL query using the query builders, which were generated by our project here. And when you write GraphQL queries or also use the data models in your favorite IDE, you can also benefit from auto-completion, which includes all the fields that are basically available in the Magento GraphQL schema. We released these data models for each new Magento version on GitHub. So feel free to use them in your custom projects. All right, let’s continue with the actual retriever pattern and how you customize it. So what you can see here on the slide is the retriever pattern as we use it in the CF core components project. So we have a separate retriever class, which gets instantiated and configured by the product sling model, which is basically part of the CF product core component. This also includes to tell the retriever which product should actually be fetched. So number one here in the code, you see that our sling model creates a new instance of the product retriever, giving a reference to the GraphQL client and sets the identifier so that the retriever knows which product to fetch. And when calling the fetch product method on the retriever, it will take care of generating a GraphQL query and using the GraphQL client to fetch the data from the commerce engine. That’s number two here. And please note for this pattern to work, it’s actually very important that you call the fetch product method in every getter that is exposed to the HDL template and not in the post construct method. The response data that’s returned by the GraphQL client is actually stored in the retriever. So the query is only executed once, even if you call the fetch method multiple times if you have multiple getters. Okay, let’s see how this works together with the sling model delegation pattern. So in a project for a custom component, you would create a custom product sling model, which delegates back to the original product sling model that’s part of the CF core components using the resource supertype. That shouldn’t be anything new. You can see here at number two, how this looks in the code. The product sling model provides access to the retriever instance. So actually your custom product sling model can access it and apply changes. So the retriever exposes some methods to extend the query in certain locations, for example, for the product and product variant attributes. So you see this number three here. We take the sling model, product sling model called the get product retriever to get the retriever instance, and then we can extend the product query to get the country of manufacture attribute. And then we also add this new attribute, which you query as a new getter. That’s number four here. And also, as you can see when working with the query and also the responses here, we actually used the craft data model classes, which I showed you earlier, which were automatically generated. And in the example here, you can also see now why it’s important that the sling model asked retriever to fetch the data only when calling a getter. This is basically just in time, just in time data fetching. And this allows the custom sling model to change the query before it’s actually executed. This makes sure the product query is only executed once, despite you have two sling models, which actually both have access to the data. Quick takeaway for this customization method. Whenever you want to customize the CF core components, for example, to add custom product attributes, use sling model delegation. Also, if you extend your components like this, one major advantage is that they stay compatible to future versions of the CF core components. So you can easily upgrade and benefit from the latest features. We use this retriever pattern in many components and retriever classes are available for many data types. Also, for lightly customized GraphQL endpoints, like when you have configured custom product attribute sets, the query builders will also let you extend the query in a more generic way, like will let you add fields which were not in the actual schema at the time of the generation of the query builders. So you can see here on the slide, we have methods like add custom simple field, which lets you add custom fields. You can also find another customization example with more details in the linked CF documentation on Adobe Experience Leak. Let’s continue with the second customization pattern. CF does not only provide you with the CF core components, but also the underlying configuration to connect to the commerce provider. And this is basically how it works. At the very left, you have the GraphQL endpoint of your commerce provider. And the CF add-on on AM as a cloud service provides a GraphQL client, which you can use to actually issue requests to this endpoint. This client is configured via an OCL configuration factory, which configures like to which endpoint the client should talk to caching credentials and which HTTP method to use and more. If you have multiple endpoints, like you want to talk to multiple commerce providers, you can also have multiple GraphQL client configurations. And if you use AM as a cloud service, the GraphQL client will be pre-configured for you. In addition, we also use CF cloud configurations, which are basically Sling context-aware configurations to configure a website to use a certain GraphQL client. These CF cloud configurations include store-specific conflicts like the Magento store code or the category ID, which should be considered the root of your catalog navigation. If you have multiple stores, like you on the slide, you see a Swiss and French store, we recommend that you use one CF cloud conflict for each of your stores or for each of your product catalogs. And any CF core component that is placed on pages of your store can automatically pick up the configuration and will have access to the GraphQL client to communicate with the commerce provider. And the best thing about this architecture is that you can use it for your custom components as well. Whenever you have a use case for component that is not covered by any of the CF core components, you can write your own component, but at the same time still leverage CF. Let me give you a quick demo of how such a component can look like. Here we have a very simple SlingModel for building a product component. And this component will just display the name and the image of a product. If we go into the implementation, you can actually see, so this is a pure standalone SlingModel, standalone component. We don’t use any SlingModel delegation or we don’t use any retriever pattern. And the only thing we are actually using from the CF core components is the Magento GraphQL client class. And this class, as mentioned earlier, is able to pick up the configuration from the context and provide you with a GraphQL client instance, which you can use to issue GraphQL requests to the commerce system. And further down, you can see how we actually now fetch the product data. We use the query builders to create a GraphQL query. So we set here the filter to set an identifier to filter for a specific product. And down here, we query for the name and the URL of an image. As I promised earlier, so you also have auto-complete for the query so you can easily extend this with all the attributes which are available in the schema. After defining the query, we use the GraphQL client to actually execute the query. We get the response from the commerce system and also here the list of products you get returned. Use the same data classes which we generated earlier. So even here, you have the auto-complete to have access to all the custom, all the attributes in the GraphQL schema. For our complete list, let me also show you how this component looks like in AM. So we have the mini product component here, which I can track and drop onto the page in our Vinya store. So the store is configured, has the configuration available. So the component can pull the product data from the commerce provider and display the product data. You can also find the link to the complete example, which I just showed you at the end of the slides. Quick takeaway for this way of customizing. Whenever you have a use case, which is not covered by any of the CF core components, for example, components for B2B use cases, you can still leverage the GraphQL client, which is provided by CF to speed up your component development. The Magento GraphQL client class, which I showed you, is actually a wrapper around the more generic GraphQL client. And this wrapper adds some Magento specific features like store selection, access to a staged catalog with AM launches and caching. The GraphQL client class, however, can also be used directly using a convenient adapter factory like you can see here on the slide. And you can also use it to send queries to any kind of GraphQL endpoints independently of the commerce use case. And also this GraphQL client is available open source on GitHub. So feel free to also use it for your other projects. Let’s continue with the final extension pattern, which you can use when you want to heavily customize your GraphQL endpoint. Let me again first explain for when you want to use this kind of extension pattern. Out of the box, you have your AM storefront, which will fetch data from a commerce engine via GraphQL. Now in case you want to retrieve data from another service, for example, like an inventory management system, you need some kind of middle layer to federate multiple data sources into a single GraphQL endpoint. Now you might ask, why don’t we use multiple GraphQL endpoints? And yes, you can do this. And in some use cases, this even makes sense. But especially if we talk about connected data, like inventory information for a specific product, it’s very convenient when you can relate that data directly in a single GraphQL query. And I will show you this in more detail on the next slide. As part of CAF, we provide a GraphQL integration layer, which is basically a GraphQL server that runs on serverless infrastructure, such as like Adobe AI runtime. And this layer makes it very easy to federate data from multiple services, even if they don’t support GraphQL, to add custom logic, or to integrate with third party commerce engines. Okay, let me give you an example how this could work. Let’s say you want to customize your product component to display inventory information, like which stores have the product available in stock. What you want to do first is to extend your GraphQL schema to expose this inventory information. You see an example query here. So you create for the product and also for the inventory with the location attribute. To actually display this information, you can use the Sling Model Delegation pattern, which I showed you earlier, to customize the CAF core product component to update the query or to extend the query to create for this additional attributes. The challenge here, however, is that the data is not stored in your commerce engine directly, but in an external inventory management system. How does this data get into your schema? And to make things a bit more challenging, let’s also assume that the inventory service does not have a GraphQL API, but exposes the data using REST. So we can actually solve this kind of use case or this architecture using the GraphQL integration layer. The entry point here is the query dispatcher action, which has knowledge about your extended schema and knows how to delegate individual parts of your query using the two loaders here. So the first loader here can resolve all parts of the query, which are part of the regular Magento GraphQL schema. This is like the product part of your query, and it will just resolve it by making a query to the GraphQL endpoint of your commerce provider. The second loader delegates the query resolution for the inventory part to a special resolver. So it cannot directly go to the inventory service since the inventory service does not provide a GraphQL endpoint, but to a resolver. And the resolver will basically fetch all the data which is required to resolve this query using the REST API. After this data is basically fetched, it’s returned to the query dispatcher and it will federate these results into a single response and return to the client so that your component can basically display both the product and the inventory information. So you can see that our project here provides an easy and scalable way of implementing GraphQL servers to integrate external services with your AM project. Quick takeaways for this customization approach. So whenever you want to integrate external services to make the data available to your components, you can use the GraphQL integration layer. It’s a serverless implementation, so the performance impact is low. We have a reference implementation available on GitHub and my colleague Christoph wrote a blog post which describes the project in more detail. I have the links for both of them on the slides. And we also have partners which contribute with implementations for API translation layers for integrating with third-party commerce engines. So you can also have a look at those. All right, before we end the session and go over to the questions, let me also share a list of all the resources I presented today. So everything is open source and freely available. I highly encourage you to give it a try. Now we can continue with the questions if there are any left. So the question is, is there a roadmap for future features? Of course, we have a roadmap and I think my PM is also available here in the chat who can tease maybe some new features. But also I linked the GitHub projects for the CF Core components and the other projects we have. If you have any feature requests, feel free to create like an GitHub issue and we are happy to discuss the features with you. And of course, we also accept any contributions. Another question regarding the payment gateways for Magento. So what we actually did with our Venya sample storefront, so the shopping cart and checkout were implemented as client-side components and they directly communicate with Magento CraftQL. So whenever your payment provider, or the payment provider integration in Magento provides CraftQL support, you can use this as well. Okay, so that’s the question about the recommended patterns for customizing the client-side portion of the CF Core components. So for some of the components, we actually have typical React specific patterns, like we have hooks. So you can write like your custom React components, which use the hooks the CF Core components provide. The logic encapsulates in the hooks and you can basically write custom markup. Yeah, that’s basically the recommended customization pattern, but there’s still a lot of work to do to make it as customizable as the server-side components. So again, if you have any specific needs here, feel free to create a GitHub issue and we can discuss this with you. For CF specifically, we also have a public Slack channel, which we can share with you. Other than that, if you have any further questions, we have a forum post, which you can ask for the questions, but feel free to join the Slack channel where we will answer all CF related questions. Okay, so there’s another question regarding the data layer integration. Yes, we also have data layer integration for our components. I think that’s part of the recent releases. That’s actually quite a new feature and this works for both the server-side and the client-side components. All right, so regarding the checkout implementation. The way how we implemented the cart and the checkout components. So the components are client-side and they communicate directly with the Magento GraphQL endpoint. All cart-specific functionality or payment functionality, which is exposed via the Magento GraphQL endpoint can be used. This basically bypasses AM directly. The components directly communicate with Magento. And the actual payment flow depends a bit on what kind of payment provider you use. So out of the box, we also have an example how the payment provider works. So you can have a look at this, but I think if you want to use any other kind of payment provider, you might need to customize the components for this. It will not go through a CRF, but like all the providing like the end point that works through CRF, like the whole configuration that the components know to which Magento instance to talk to. This works via CRF, like the configuration as I showed in the slides earlier, but the communication does not go through the AM JVM. It goes directly to Magento. Yes, exactly. As Marco said, for PCI reasons, we do not go through AM with those kinds of data. All right, so time’s up. Thanks a lot. And let’s continue on the main stage. Thank you.

Click here for the session slides.

recommendation-more-help
3c5a5de1-aef4-4536-8764-ec20371a5186