Skip to content

amarpatel-xx/jhipster-ai-postgresql-example

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

104 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

JHipster Example for Human-Readable Foreign Keys in User Interface

About this JHipster Example

This code was generated using the JHipster blueprint generator-jhipster-ai-postgresql. The source code for the underlying JHipster generator that is used in this example is available at: https://github.com/amarpatel-xx/generator-jhipster-ai-postgresql

This code has a JDL which shows 2 foreign keys that will concatenated and shown, in the Angular user interface, in replacement of the UUID. The JDL can be modified and the @customAnnotation("DISPLAY_IN_GUI_RELATIONSHIP_LINK") can be used with any fields of an entity which would make it easier to identify that entity when displayed (as part of a relationship). Sometimes having a UUID makes it difficult for the human in the loop to figure out what the entity on a relationship's other side actually is. If multiple entity fields are necessary to replace the UUID, the fields can be delimmited via a specified delimiter using a @customAnnotation, as well (see the example JDL file included as part of this project).

Matt Raible's frequently used the blog and store examples in his capability demonstrations.

  1. Below is the example using the @customAnnotation and specifying the delimiter also.
    entity Blog {
      @customAnnotation("DISPLAY_IN_GUI_RELATIONSHIP_LINK") @customAnnotation("-") name String required minlength(3)
      @customAnnotation("DISPLAY_IN_GUI_RELATIONSHIP_LINK") @customAnnotation("-") handle String required minlength(2)
    }

    entity Post {
      title String required
      content TextBlob required
      date Instant required
    }

    relationship ManyToOne {
      Blog{user(login)} to User
      Post{blog} to Blog
    }

Improvements Since v2.0.14

The underlying generator-jhipster-ai-postgresql blueprint has received significant improvements since the last open-source tagged release (v2.0.14). Regenerating this example with the latest blueprint version will include:

pgvector / AI Semantic Search

  • Added full PostgreSQL pgvector support for AI-powered semantic search on entity fields.
  • Automatic embedding generation on create and update -- when an entity with vector fields is saved, embeddings are generated from source text fields (e.g., name -> nameEmbedding) using the OpenAI Embedding API.
  • AI semantic search bar on list pages for entities with vector fields -- users can type natural language queries and find semantically similar records.
  • Vector embedding fields are automatically excluded from DTOs to keep payloads clean, while remaining in JPA entities for database operations.
  • Cosine similarity search with distance threshold filters out unrelated results -- only semantically relevant matches are returned.
  • HNSW indexes are automatically created on vector columns for fast approximate nearest neighbor search.
  • Generates EmbeddingConfiguration with Spring AI and OpenAI embeddings (text-embedding-3-small, 1536 dimensions).
  • PgVectorConverter with autoApply=true handles float[] <-> PostgreSQL vector serialization transparently.
  • Automatic embedding migration on startup -- similar to how Liquibase runs, embeddings are generated for any rows missing them.
  • Angular UI shows vector fields as readonly on update forms and truncates long vector arrays on list and detail pages.

JDL Configuration for Vector Fields

The Tag entity in this example uses @customAnnotation("VECTOR") to enable AI semantic search:

entity Tag {
  id UUID
  @customAnnotation("DISPLAY_IN_GUI_RELATIONSHIP_LINK") @customAnnotation("") name String maxlength(100) required
  description String maxlength(255)
  @customAnnotation("VECTOR") @customAnnotation("1536") nameEmbedding Blob
  @customAnnotation("VECTOR") @customAnnotation("1536") descriptionEmbedding Blob
}

How the annotations work:

  • @customAnnotation("VECTOR") -- Marks the field as a pgvector embedding field. The blueprint converts it from Blob to float[], generates the vector(N) column type in Liquibase, and adds the AI search infrastructure.
  • @customAnnotation("1536") -- Specifies the vector dimension (1536 for OpenAI's text-embedding-3-small model).
  • The embedding field name must follow the pattern <sourceField>Embedding (e.g., nameEmbedding derives from name, descriptionEmbedding derives from description). The blueprint auto-generates embeddings from the source field's text value on every create and update.
  • The AI search bar queries all embedding fields in the entity, merges results, and deduplicates by ID -- so a match on either name or description will surface the entity.

AI Semantic Search Screenshots

Searching for "camry" returns Toyota (a car brand) and Cat (less relevant, ranked lower):

Semantic Search - Camry

Searching for "cheetah" returns Cat first (both are felines), then Dog and Toyota ranked by similarity:

Semantic Search - Cheetah

Searching for "german shepherd" returns Dog first (a dog breed), then Cat (also an animal), then Toyota (least similar):

Semantic Search - German Shepherd

PDF Blob Support

  • Added PDF thumbnail and download support for blobContentTypeAny fields in list, detail, and update page templates.
  • PDF icon styling matches across list and detail views with shadow and download link.
  • Added null-safe openFile() for blob fields.

Performance Optimizations

  • Added Entity Graph backend repository support for eager-loading related entities in a single query, avoiding N+1 problems.
  • Added a feature to ignore massive entity relationship lists on view and update pages, keeping the UI responsive and performant.
  • Fixed toDTO mapping performance issues by preventing MapStruct infinite recursion on bidirectional relationships.
  • Added a non-paginated criteria endpoint for cases where full result sets are needed without pagination overhead.

UI and Template Improvements

  • Added navbar menu grouping and alphabetical sorting for microfrontend entity menus.
  • Simplified entity graph handling and REST resource templates.
  • Added ExceptionTranslator patching to log full stack traces at ERROR level for better debugging.

Prerequisites:

AI Semantic Search (Optional)

To enable AI-powered semantic search, set your OpenAI API key as an environment variable:

export OPENAI_API_KEY=sk-your-key-here

Or add it to your microservice's application-dev.yml:

openai:
  api-key: sk-your-key-here

Without the API key, the application runs normally but embedding generation and AI search are disabled.

Build

Build Java Microservices using the Multiple Human-readable Foreign Key Fields Blueprint

  1. To generate a microservices architecture with human-readable foreign key fields support, run the following commands:
npm install -g generator-jhipster-ai-postgresql

git clone https://github.com/amarpatel-xx/jhipster-ai-postgresql-example.git

cd jhipster-ai-postgresql-example

Mac / Linux:

sh saathratri-generate-code-dev-sql.sh

Windows:

saathratri-generate-code-dev-sql.bat
  1. You should see the message:
Congratulations, JHipster execution is complete!

Run your Multiple Human-readable Foreign Key Fields Example

  1. When the process is complete, cd into the psqlgateway directory and start Keycloak and Eureka using Docker Compose.
cd psqlgateway
docker compose -f src/main/docker/keycloak.yml up -d
docker compose -f src/main/docker/jhipster-registry.yml up -d
  1. Start psqlgateway database with Docker by opening a terminal and navigating to its directory and running the Docker command. Then start the gateway by running the Maven command.
npm run docker:db:up
./mvnw spring-boot:run -Dspring-boot.run.profiles=dev
  1. Start pslqblog database with Docker by opening a terminal and navigating to its directory and running the Docker command. Then, start the blog microservice.
cd psqlblog
npm run docker:db:up
./mvnw spring-boot:run -Dspring-boot.run.profiles=dev
  1. Start psqlstore database with Docker by opening a terminal and navigating to its directory and running the Docker command. Then, start the store microservice.
cd psqlstore
npm run docker:db:up
./mvnw spring-boot:run -Dspring-boot.run.profiles=dev

Switch Identity Providers

JHipster ships with Keycloak when you choose OAuth 2.0 / OIDC as the authentication type.

If you'd like to use Okta for your identity provider, see JHipster's documentation.

You can configure JHipster quickly with the Okta CLI:

okta apps create jhipster

See the Code in Action

Now you can open your favorite browser to http://localhost:8080, and log in with the credentials displayed on the page.

Then create a Blog

  1. Open your favorite browser to http://localhost:8080, and log in with the credentials displayed on the page. Then navigate to the psqlblog menu item.
  2. Then, add a user by giving it a login name.
  3. Then, add a blog by giving it a name, handle and selecting the user.
  4. Add a tag by giving it a name and description. If the OpenAI API key is configured, embeddings are automatically generated when you save.
  5. Finally, add a post by providing a title, content, selecting the blog and the tag.

Notice the blog column of the post shows <blog-name>-<blog-handle> and not the UUID of the blog. That is success!

Try AI Semantic Search

If you configured the OpenAI API key, go to the Tag list page and use the AI Search bar. Type a natural language query (e.g., "animals" or "vehicles") and the search will find tags with semantically similar names or descriptions using cosine similarity against pgvector embeddings.

Then create a Store

  1. Open your favorite browser to http://localhost:8080, and log in with the credentials displayed on the page. Then navigate to the psqlstore menu item.
  2. Then, add a product by giving it a title, a price and an image.

Have Fun with Micro Frontends and JHipster!

I hope you enjoyed this demo, and it helped you understand how to build better microservice architectures with human-readable foreign key fields.

☕️ Find the code for the underlying blueprint used here to generate a JHipster application on GitHub: https://github.com/amarpatel-xx/generator-jhipster-ai-postgresql

☕️ Find the example code that uses the blueprint to generate a JHipster application on GitHub: https://github.com/amarpatel-xx/jhipster-ai-postgresql-example

🤓 Read the following blog post, by Matt Raible, that was used as inspiration for this project: Micro Frontends for Java Microservices

Acknowledgements

Thank you to Matt Raible and Gaël Marziou for your invaluable contributions to this example and the underlying JHipster blueprint.

About

This code was generated using the JHipster blueprint "generator-jhipster-ai-postgresql". It supports human-readable foreign keys via @customAnnotation("DISPLAY_IN_GUI_RELATIONSHIP_LINK") and AI semantic search via pgvector and OpenAI embeddings using @customAnnotation("VECTOR").

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors