A Hasura Quick Start with Remote Schema, Remote Joins

I’ve been building GraphQL APIs for a number of years now – of along side RESTful, gRPC, XML, and other API styles I won’t even bring up right now – and so far GraphQL APIs have been great to work with. The libraries in different languages form .NET’s Hot Chocolate, Go’s graphql-go, Apollo’s JavaScript based tooling and servers, to Java’s GraphQL for Spring have worked great.

Sometimes you’re in the fortunate situation where you’re using PostgreSQL or SQL Server, or other supported database for a tool like Hasura. Being able to get a full GraphQL (with REST options too) API running in seconds is pretty impressive. From a development perspective it is a massive boost. As Hasura adds more database connectors as they have with Snowflake and Amazon Athena, the server and tooling becomes even more powerful.

With that I wanted to show a N+1 demo where N is day 1 with Hasura. The idea is what do you do immediately after you get a sample service running with Hasura. How do you integrate it with other services, or more specifically how do you integrate your Hasura API along side APIs you’ve written yourself, such as an enterprise GraphQL for Spring based API running against Mongo or other data source? This repo is the basis for several demonstration repositories I am building that will show how you can setup – generally for local development – Hasura + X API with Y Language stack.

This is the Hasura quick start repository here, with migrations and metadata for a local setup. The first demonstration repo for a peripheral GraphQL API will be a Spring based API in this repository. The following steps will get the quick start repository up and running.

  1. Clone this repo git clone git@github.com:Adron/hasura-quick-start.git.
  2. From the root (where the docker-compose.yml file is located) execute docker compose up -d.
  3. Navigate into the hasura directory.
  4. Execute hasura metadata apply, then hasura migrate apply, and then hasura metadata apply. Just do it, it’s a strange workflow thing.
  5. Navigate now into the `hasura` directory and execute hasura console.

These steps are demonstrated in this video from 48 seconds.

What do you get once deployed?

The following are some of the core capabilities of Hasura and showcase what you can get up and running in a matter of seconds, even when you start from a completely empty database! First off you’ll find the database now has 3 tables along with their pertinent schema built out in PostgreSQL and available via Hasura, as shown here under the Data tab of the console.

I also created a schema diagram just to provide a visual of how these tables are designed.

For the remote schema, the Spring API, the following steps will get it cloned and running locally.

  1. Clone this repo git clone git@github.com:Adron/hasura-spring-boot-graphql.git.
  2. Execute ./gradlew build to get the jar file build. It will then be located in the build/libs directory of the project.
  3. Next build the docker image with docker build -t adron/hasura-spring-boot-graphql . to build the docker image locally.
  4. Now you can either start this container with docker compose up -d using the docker-compose.yml in the project or you can run the image with Docker specifically with docker run -p 8081:8080 adron/hasura-spring-boot-graphql.

For a walkthrough of getting the Spring API running, check out 2:28 onward in this video.

Now both of these instances are running locally and you can test each out respectively, but not specifically together. I’ll have probably write up another post on how to get services that spin up separately to run together for localized development. However, with the way things are setup in the two repos, it’s as if one team is the Hasura team building a GraphQL API and another is a Spring Java GraphQL API team, and they’re working autonomously of each other just based on contract of the APIs themselves.

Remote Schema

With that being the scenario, I’ve deployed the Spring API out remotely so that I could show how to put together a remote schema connection and then a remote join query, i.e. nested query in GraphQL speak, across these two APIs.

To add the remote schema, click on the remote schemas tab on the console. Add a name (1), then the URI (2), and optionally if needed add appropriate headers (3) or forward all headers from client requests.

Once that’s added, navigate to the relationships tab of the new remote schema and click on add. Then for this example, select remote database (1), then add a name (4) (Customer in the example) and then for type choose object (3) (per the example).

Then scroll down on that console screen and choose sales_data (1) and default, public, and users (2) under the reference database, schema, and table. Next up choose the source field (3) and reference column (4).

Once added it will look like this in the console.

This creates a relationship to be able to make nested queries against these sources with GraphQL. If it were a single contiguous database the schema would look like this. I’ve color coded the sales_data table as red, to signify it is the table we know is in another database (or, specifically, provided via another hosted API). However, as stated, in a single database the relationships would now look like this. The relationship however, isn’t in a database, but stored in the Hasura metadata between users and sales_data.

Now writing a query across this data would shape up like this. Because of the way the relationship was drawn via the remote schema, the path to get the nested object Customer (2) for the sales data is to start with the sales_data (1) entity. As shown.

sales_data {
  sales_number
  updated_at
  Customer {
    name
  }
}

Now we want to add more details about the particular customer like their email and details. To do this we’ll utilize another nesting level within this query that delves into relationships that are in the PostgreSQL database itself.

sales_data {
  sales_number
  updated_at
  Customer {
    name
    emails {
      email
    }
    details {
      details
    }
  }
}

With this the nested details email (3) and details (4) will be provided, which is foreign key relationships to the primary key table users in the underlying database, made available by Hasura’s relationships in metadata.

Boom! That’s it. Pretty easy setup if the databases and APIs have Hasura available to connect them in this way. Otherwise, this is a huge challenge to develop against if you’re just using solely a tech stack like Apollo, Spring Boot, or Hot Chocolate. Often something along federation and more complexities would come into play. But more on that later, I’ve got a piece coming on federation, stitching, remote schemas, and gateway – among various ways – to get multiple GraphQL, or GraphQL and RESTful APIs together into a singular, or singularly managed, API end point.

Hope that was useful, if you’ve got comments, questions, or curiosities let me know in the comments here, or pop over to the video and leave a comment there.

References:

The full video of setup and how the remote schema & joins work in Hasura.

Gradle Build Tool

A few helpful links and details to where information is on the Gradle Build Tool.

Installation

Via SDKMAN sdk install gradle x.y.z where x.y.z is the version, like 8.0.2.

Via Brew with brew install gradle.

Manually check out the instructions here.

Building a Java Library (or application, Gradle plugin, etc)

Using the init task. From inside a directory with the pertinent project.

gradle init

You’ll be prompted for options.

With the project initialized this is what that initialized folder structure looks like.

At this point add the Java code for the library, similar to this example, and execute a build like this.

./gradlew build

Build Collateral

View the test report via the HTML output file at lib/build/reports/tests/test/index.html.

The JAR file is available in lib/build/libs with the name lib.jar. Verify the archive is valid with jar tf lib/build/libs/lib.jar.

Add the version by setting the version = '0.1.1' in the build.gradle file.

Run the jar task ./gradlew jar and the build will create a lib/build/libs/lib-0.1.1.jar with the expected version.

Add all this to the build by adding the following to the build.gradle file:

tasks.named('jar') {
    manifest {
        attributes('Implementation-Title': project.name,
                   'Implementation-Version': project.version)
    }
}

Verifying this all works, execute a ./gradlew jar and then extract the MANIFEST.MF via jar xf lib/build/libs/lib-0.1.0.jar META-INF/MANIFEST.MF.

Adding API Docs

In the */Library.java file, replace the / in the comment by / * so that we get javadoc markup.

Run the ./gradlew javadoc task. The generated javadoc files are located at lib/build/docs/javadoc/index.html.

To add this as a build task, in build.gradle add a section with the following:

java {
    withJavadocJar()
}

Publish a Build Scan

Execute a build scan with ./gradlew build --scan.

Common Issues + Tips n’ Tricks

gradlew – Permission Denied issue

Let’s say you execute Gradle with ./gradlew with whatever parameter and immediately get a response of “Permission Denied”. The most common solution, especially for included gradlew executables included in repositories, is to just give the executable permission to execute. This is done with a simple addition chmod +x gradelw and you should now be ready to execute!

Interviewing AI. AI has thus answered the questions on AI in Software Development!

Me: Describe to me how AI is changing software development and the work developers do daily.

The AI: AI is transforming software development in various ways, ranging from automating repetitive tasks to enhancing software performance and user experience. Here are some specific ways that AI is changing software development and the work developers do daily:

  1. Automating mundane tasks: AI has enabled developers to automate various repetitive tasks that were previously done manually. For instance, using machine learning algorithms, AI can automate code review and testing, freeing up developers’ time to focus on more complex tasks.
  2. Enhancing software performance: With AI, developers can create more robust and efficient software. AI algorithms can analyze code and identify performance issues, potential bugs, and other areas that can be improved. This makes it easier for developers to optimize code and improve overall software performance.
  3. Improving user experience: AI can be used to enhance user experience in various ways. For instance, AI can be used to analyze user behavior and preferences, allowing developers to create more personalized and intuitive interfaces. AI can also be used to provide real-time feedback and recommendations to users, making software more engaging and interactive.
  4. Increasing productivity: AI-powered tools and frameworks can help developers be more productive by automating repetitive tasks, suggesting solutions to problems, and speeding up the development process.
  5. Facilitating collaboration: AI-powered tools can facilitate collaboration among developers by identifying areas where different developers can work together, highlighting common issues, and recommending solutions.

Overall, AI is transforming software development by making it more efficient, effective, and collaborative. As AI continues to evolve, developers will likely see even more changes in the way they work and the software they produce.

Me: What are ways that software developers can prepare for the changes AI is bringing to software development?

The AI: As AI continues to disrupt the software development industry, software developers need to prepare for the changes that are coming. Here are some ways that software developers can prepare for the changes AI is bringing to software development:

  1. Stay informed: Developers need to keep up with the latest trends and developments in AI and machine learning. This includes reading industry publications, attending conferences, and participating in online forums.
  2. Learn new skills: Developers should invest in learning new skills that will be valuable in an AI-driven future. This includes understanding machine learning algorithms, natural language processing, and data analysis techniques.
  3. Collaborate with AI experts: Developers can collaborate with AI experts to learn more about AI technologies and how they can be applied to software development. This can involve working on joint projects, attending meetups, and networking with AI experts.
  4. Embrace automation: Developers need to be open to automation and embrace tools that can automate repetitive tasks. This includes using AI-powered code review and testing tools, as well as automated build and deployment systems.
  5. Focus on the user: Developers should focus on creating software that delivers value to users. AI can be used to create more personalized and intuitive interfaces that enhance the user experience. By focusing on the user, developers can stay ahead of the curve and ensure that their software remains relevant.
  6. Develop a growth mindset: Lastly, developers should develop a growth mindset that enables them to embrace change and learn new skills. This includes being open to feedback, seeking out new challenges, and continuously improving their skills.

In summary, by staying informed, learning new skills, collaborating with AI experts, embracing automation, focusing on the user, and developing a growth mindset, software developers can prepare themselves for the changes AI is bringing to software development.

Me: What effects might AI cause in the developer job market with the reduction and automation of work that many software developers do today?

The AI: The increasing adoption of AI in software development is likely to have a significant impact on the job market for software developers. While AI will create new job opportunities in areas such as data science and machine learning, it may also lead to the reduction and automation of work that many software developers do today. Here are some potential effects:

  1. Automation of repetitive tasks: As AI-powered tools become more prevalent, developers may find that many of the tasks they previously performed manually are automated. This could include tasks such as testing, debugging, and code review. While this will free up developers’ time to focus on more complex tasks, it may also lead to a reduction in the number of jobs available.
  2. Shift in skill requirements: As AI becomes more prevalent, the skills required to be a successful software developer may change. Developers may need to have a greater understanding of machine learning algorithms, data analysis, and natural language processing. This may lead to a shift in the education and training required for software development.
  3. Emergence of new job roles: While some jobs may be automated, AI is also likely to create new job opportunities in areas such as data science, machine learning engineering, and AI architecture. These jobs may require a different set of skills and expertise than traditional software development roles.
  4. Increased competition: As the number of jobs available in software development potentially decreases, competition for the remaining jobs may increase. This may put pressure on developers to constantly update their skills and stay relevant in the job market.

Overall, the impact of AI on the job market for software developers is likely to be complex and multifaceted. While some jobs may be automated or reduced, new job opportunities may emerge. Developers who stay up-to-date with the latest trends and developments in AI and machine learning will be better positioned to take advantage of these new opportunities.

Me: Is there any evidence that there will be a net loss of jobs when AI becomes a larger part of software development?

The AI: There is some debate among experts about the impact of AI on jobs in the software development industry. While AI will certainly lead to the automation of some tasks, it may also create new job opportunities in areas such as data science, machine learning engineering, and AI architecture.

There have been several studies on the impact of AI on jobs in the broader economy, and the results have been mixed. Some studies suggest that AI will lead to significant job losses, while others suggest that it will create new job opportunities and lead to a net gain in jobs.

In the software development industry specifically, there is evidence that the impact of AI on jobs will depend on the specific tasks and skills involved. For example, a study by Deloitte found that while AI may automate some routine programming tasks, it is unlikely to replace developers altogether. Instead, AI is likely to shift the focus of developers towards more complex tasks that require human creativity and problem-solving skills.

Another study by the World Economic Forum found that AI is likely to create new job roles in software development, such as data analysts, machine learning engineers, and AI architects. However, the study also found that there may be some displacement of jobs, particularly for those with lower skill levels.

Overall, while it is difficult to predict the exact impact of AI on jobs in software development, it is likely that there will be both job losses and job gains. Developers who are able to adapt and acquire new skills in areas such as machine learning and data analysis are likely to be better positioned to take advantage of the new job opportunities created by AI.

Summary

Funny thing, and maybe it’s all a simulation right, but AI has given you basically the same exact answers I’d give you if asked these same questions. However, I’m writing an article to add more detail that AI (at least chatGPT) has not been able to provide. If you’ve used it, you’ve probably noticed, but there are distinctive limitations to the AI’s learning so far that just isn’t equitable to a well researched and well read human writing up a piece on a topic they understand well. It appears, so far, we’re not entirely replaceable yet!

A Quick Post on URL, URI, UDI, URN… Resources

URL, or Uniform Resource Locator, is often used as a blanket term for almost anything on the internet. A URI, or Uniform Resource Identifier, represents a unique resource on a server, located somewhere on the World Wide Web. Other abbreviations that are often confusingly related include UDI for Universal Document Identifier and URN for Universal Resource Name. All together we have the following abbreviations;

  • URL – Uniform Resource Locator
  • URI – Uniform Resource Identifier
  • UDI – Universal Document Identifier
  • URN – Uniform Resource Name

A URI can be either a URL or URN.

URI Syntax

scheme:[//authority]path[?query][#fragment]
  • Scheme – This is a non-empty sequence of characters followed by a colon, followed by any combo of digits, letters, periods, hyphens, or plus characters. The scheme is registered with the Internet Assigned Numbers Authority (IANA).
  • Authority – The authority is an optional field preceded by //. It has the following subfields.
    • Userinfo – A subcomponent which could contain username and password, or other user information data.
    • Host – A subcomponent containing either an IP address or a registered host or domain name.
    • Port – An optional subcomponent that is followed by a colon.
  • Path – Contains a sequence of segments separated by a slash characters. This could be something like /resources or /trains or similar.
  • Query – An optional component preceded by a question mark. The component contains a query string of non-hierarchical data, each parameter is separated by an ampersand in the query component and parameter values are assigned using an equals operator.
  • Fragment – An optional field and is preceded by a hash. The fragment includes a fragment identifier for a secondary resource.

Examples

  • mailto:myaddress@thrashingcode.com
  • telnet://10.20.0.1:23/
  • ldap://[2020:ba6:9:9]/c=ZAZA?objectClassOfDomain?objectOfDomain

The Differentiator

The URI examples above all could be called URLs, however the difference is that a URI is an identifier, where as a URL is an identifier and provides details on how to get to the identified resource.

URN AKA Uniform Resource Name

URNs are not used often. More specific details can be found in RFC 2141. For this quick post it’s safe to sort of ignore URNs, as the other abbreviations are the ones you will see out and about in the world, and specifically used in detailing REST APIs and the like.

Vue.js Studies Day 6 – Beyond “Getting Started”

The previous post to this one, just included some definitions to ensure I’ve covered the core topics as I’m moving along. Before that I covered getting a project app started in day 3 and day 2 posts. Before that I covered the curriculum flow I’m covering in these studies.

Now that I’ve covered a number of ways to get started with a Vue project with; JetBrains WebStorm, hand crafted artisanal, or via NPM it’s time to start covering the basics of how to build an app using Vue.js. I’ll be using the WebStorm IDE for development but will still call out where or what I’d need to do if I were working from the terminal with something else. By using the WebStorm IDE, I’ll also be starting from the generated app that the IDE created for me.

main.js

Starting in the src directory of the project, let’s cover a few of the key parts of this project of the application as created. First, we have a main.js file. In that file is the following code. This little bit of code is what is responsible for working with the Virtual DOM to mount the application to it for rendering the page we eventually see.

import { createApp } from 'vue'
import App from './App.vue'

import './assets/main.css'

createApp(App).mount('#app')

The first two lines import two variables from the ‘vue’ library called createApp and create an App object from ‘./App.vue’ template. Then the third import is just pulling in the main.css file. The fourth line uses the createApp operatig on the App object to .mount the application at the point of the #app anchor in the template App.vue. That leads to needing to take a look at App.vue to see what exactly the vue app is mounted to.

NOTE: I’m not 100% sure I’m describing this as precisely as I should, as the blog entry details, this is day 4 of Vue.js studies. I’d started in the past once or twice, and have done a ton of web dev over the years, but Vue.js is largely new to me. So if you see something worded incorrectly or oddly, please comment with questions or corrections.

App.vue

The App.vue file for the WebStorm generation seems to have a bit more from the other apps generated from other tooling. Whatever the case, let’s pick this apart and learn what is which and which is what in this file.

<script setup>
import HelloWorld from './components/HelloWorld.vue'
import TheWelcome from './components/TheWelcome.vue'
</script>

<template>
  <header>
    <img alt="Vue logo" class="logo" src="./assets/logo.svg" width="125" height="125" />

    <div class="wrapper">
      <HelloWorld msg="You did it!" />
    </div>
  </header>

  <main>
    <TheWelcome />
  </main>
</template>

<style scoped>
header {
  line-height: 1.5;
}

.logo {
  display: block;
  margin: 0 auto 2rem;
}

@media (min-width: 1024px) {
  header {
    display: flex;
    place-items: center;
    padding-right: calc(var(--section-gap) / 2);
  }

  .logo {
    margin: 0 2rem 0 0;
  }

  header .wrapper {
    display: flex;
    place-items: flex-start;
    flex-wrap: wrap;
  }
}
</style>

Right at the beginning of the App.vue file there is a <script setup></script> section that imports two other components that are located in the components directory that the App.vue file is located in. This is the HellowWorld.vue and TheWelcome.vue components. There is a third component, the WelcomeItem.vue component, in the component directory along with an icons directory.

With all of these assets now ready, clicking on the play or debug buttons in WebStorm will issue to the command to execute and display the app in the default browser. I’ll cover more of the assets as we get to each of them, for now I’m going to move along and get into some components and all.

When the IDE (or you do manually) launches the browser to display the app it will look like this.

Checkpoint: Vue App Operational

This is a good time to checkpoint. If you’ve been following along and everything is as shown above, we’re good to move along to the next steps. If not, then something is amiss, probably broken, and that needs resolved first. If you’ve run into a problem at this point, leave a comment with a description of the issue and I’ll endeavor to help you resolve the problem. Otherwise, moving along to some edits and checking out Vue.js’s features and capabilities.

Once the next post is live, I’ll add the link here to that post… it’s coming soon!