visit
is a Java (8+) annotation processing framework which auto generates APIs for based data models. It spans the full API stack; from data access to client side consumption. Apifi is centered around one simple goal: To eliminate the need for generic CRUD related boilerplate without compromising on control and customizability.
This means no service beans implementing generic CRUD logic, no manual GraphQL setup, no JpaRepositories, no web controller. All of that’s taken care of. You just focus on what makes your project unique, no boilerplate required.TLDR; Apifi can instantly turn any JPA data model into a GraphQL API, no boilerplate code required.
<dependencies>
<dependency>
<groupId>dev.sanda</groupId>
<artifactId>apifi</artifactId>
<version>0.0.5.4</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
Customer
Product
Archivable is an interface defined within Apifi containing two methods:
Boolean getIsArchived();
void setIsArchived(Boolean isArchived);
ShoppingCart
CustomerOrder
Note the @Transient ShoppingCart “fromCart” field in CustomerOrder. Transient fields exist in memory only and are not included in the database schema. We’ll demonstrate why this one is here a bit further down.
In order to turn this data model into a fully functional GraphQL API, we just need to add a few annotations. The first annotation which we’ll see as applied to the Customer class is
@WithCrudEndpoints(...)
:This annotation allows us to define GraphQL queries and mutations with respect to the annotated class. In this case:createCustomer ( input CustomerInput ) Customer
customerById ( input Long ) Customer
Next, we’ll use the same annotation on the Product class to define a
createProducts ( input [ProductInput] ) [Product]
mutation:Next up is ShoppingCart. We’ll be using the @EntityCollectionApi(...) annotation this time:
This annotation allows us to define GraphQL queries and mutations with respect to the annotated Collection type field. In this case:
The associatePreExistingOnly = true flag denotes that only preexisting Product objects are allowed as input to the associateProductsWithShoppingCart mutation (This makes sense in our case — you can’t add products to a shopping cart if they’re not already in the inventory). If a non existent Product object were to be passed to the associateProductsWithShoppingCart mutation an exception would be thrown, terminating and rolling back the operation.
Last but not least, customers need to check out and complete their purchase after filling up their shopping carts. To do this, we’ll once again use the
@WithCrudEndpoints(...)
annotation:This will create acreateCustomerOrder ( input CustomerOrderInput ) CustomerOrder
mutation.The only requirement now left to complete is the customer checkout logic. As briefly mentioned above, when a customer checks out by creating a new CustomerOrder, the following should happen:
In order to apply the required logic to the createCustomerOrder mutation, we create a bean class which we’ll call CustomerOrderApiHooks. This class will implement the ApiHooks<CustomerOrder> interface, and override the preCreate method. ApiHooks is an interface we can implement in order to inject custom logic before and after CRUD operations.
CustomerOrderApiHooks
And that’s it, all that’s left now is to see it in action:Also published behind a paywall at: //medium.com/swlh/instantly-deploy-java-graphql-apis-using-apifi-quick-start-eb2406f6859