A growing suite of namespaces. Require and go.
🔍
Live Bean & Property Inspection
Query any Spring bean, map the full dependency wiring graph, and inspect @Transactional boundaries — propagation, isolation, and read-only flags for every method. Find coupling smells and transaction misconfigurations in one call. All against the running app, no source reading required.
;; wiring graph — auto-filtered to your own classes
(lw/all-bean-deps)
;; @Transactional surface of all app beans
(lw/all-bean-tx)
;; => [{:bean "bookService" :methods [{:method "archiveBook" :read-only false …} …]} …]
🗄️
SQL & JPQL Execution
Run JPQL via the live EntityManager or raw SQL through the DataSource — with Hibernate type converters, active @Filters, and real transaction semantics. Prefer JPQL for entity data; raw SQL for DB-level metadata (indexes, constraints).
;; JPQL — no schema prefix, entity property names, paged by default
(jpa/jpa-query
"SELECT b.title AS title, COUNT(lr) AS loans
FROM Book b JOIN b.loanRecords lr
GROUP BY b.id, b.title
ORDER BY COUNT(lr) DESC"
:page 0 :page-size 5)
;; => [{:title "The Green Bay Tree", :loans 7}
;; {:title "Let Us Now Praise Famous Men", :loans 7}
;; {:title "Vanity Fair", :loans 7} ...]
🔬
SQL Tracing & N+1 Detection
Wrap any call with trace-sql and see every SQL it fires. detect-n+1 automatically groups repeated queries and flags suspects — in one call.
(trace/detect-n+1
(trace/trace-sql
(lw/in-readonly-tx
(.getAllBooks (lw/bean "bookService")))))
;; => {:suspicious-queries
;; [{:sql "select ... from book_genre ...", :count 200}
;; {:sql "select ... from review ...", :count 200}]
;; :total-queries 481, :duration-ms 226}
🔐
run-as — Call Secured Beans Directly
Set a Spring SecurityContext for the duration of a REPL call. Call @PreAuthorize-guarded controllers and services directly — no more bypassing to the service layer.
(lw/run-as ["alice" "ROLE_MEMBER"]
(.getBookById
(lw/bean "bookController")
(long 25)))
🔥
Live @Query Hot-Swap
Replace any Spring Data JPA @Query live — no restart. Fix it, verify it, write it back to source. Works by patching three internal layers of Spring Data JPA + Hibernate in concert.
(hq/hot-swap-query!
"bookRepository"
"findAllWithAuthorAndGenres"
"SELECT DISTINCT b FROM Book b
JOIN FETCH b.author
LEFT JOIN FETCH b.genres
LEFT JOIN FETCH b.loanRecords")
;; [hot-queries] hot-swapped ✓
🏗️
Hibernate Entity Introspection
Inspect any entity's live Hibernate metamodel: table name, column mappings, relation definitions, fetch strategies. No annotation parsing — the live metamodel is the source of truth. Use inspect-entity for one entity or inspect-all-entities to get the full domain model in a single call — perfect for agents building ER diagrams.
(intro/inspect-all-entities)
;; => {"Book" {:table-name "book", :identifier {...}, :properties [...]}
;; "Author" {:table-name "author", ...}
;; ...}
🗺️
HTTP Endpoint Introspection
Discover every registered route with its auth requirements, parameter sources, and required/optional flags — all from the live RequestMappingHandlerMapping. Resolved :required-roles and :required-authorities let you construct a lw/run-as call mechanically, without parsing the raw SpEL string.
(intro/list-endpoints)
;; => [{:paths ["/api/books/{id}"], :methods ["GET"],
;; :required-roles ["MEMBER"],
;; :parameters [{:source :path, :required true,
;; :type "java.lang.Long"}]}
;; ...]
👁️
Query Watcher — Auto-apply on Recompile
Livewire watches your compiled output directory and automatically applies any changed @Query JPQL to the live JVM within 500 ms of a recompile — no REPL call needed. Last one wins: a recompile overrides a REPL swap, and a new REPL swap overrides the last recompile.
;; just recompile — watcher applies the change
;; [query-watcher] detected change
;; bookRepository#findByIdWithDetails
;; [hot-queries] watcher re-swapped ✓
(qw/status)
;; => {:running? true, :disk-state-size 8}
🧩
JPQL with Smart Entity Serialization
Run any JPQL query via the live EntityManager and get back plain Clojure maps — no .toString() surprises. Lazy collections render as "<lazy>" rather than firing surprise queries. Scalar projections (SELECT expr, …) are unpacked into maps using AS aliases or positional :col0, :col1 keys. Paged by default.
(jpa/jpa-query
"SELECT b.title AS title, COUNT(lr) AS loans
FROM Book b JOIN b.loanRecords lr
GROUP BY b.id, b.title
ORDER BY COUNT(lr) DESC"
:page 0 :page-size 5)
;; => [{:title "Vanity Fair", :loans 7}
;; {:title "The Green Bay Tree", :loans 7} ...]
🎯
Controller Endpoint Probing
Call any Spring bean method under a live SecurityContext and get back proper JSON — serialized with the exact same Jackson ObjectMapper Spring MVC uses. List results are capped at 20 by default and returned with {:total :returned :content-size :content-size-gzip} metadata so you always know the full picture.
lw-call-endpoint bookController getBooks ROLE_MEMBER
;; ^{:total 200, :returned 20,
;; :content-size 515299, :content-size-gzip 82995}
;; [{"id" 1, "title" "All the King's Men",
;; "author" {"id" 6, ...}, "genres" [...]} ...]
;; or from the REPL:
(mvc/serialize
(lw/run-as ["u" "ROLE_MEMBER"]
(.getBooks (lw/bean "bookController")))
:limit 3)
🔎
Mutation Observer — what did that service call write?
Snapshot an entity before and after calling a service method. The thunk runs in a transaction that always rolls back — the database is never touched — but the diff captures exactly what changed.
Useful for discovering unintended writes, verifying a fix changed exactly the right fields, or systematically calling suspect service methods until the guilty one confesses.
(q/diff-entity "Book" 100
(fn [] (.archiveBook (lw/bean "bookService") 100)))
;; => {:before {:archived false, :archivedAt nil, ...}
;; :after {:archived true, :archivedAt "2026-03-28T16:16:20", ...}
;; :changed {:archived [false true]
;; :archivedAt [nil "2026-03-28T16:16:20"]}}
🗺️
Method-level Dependency Fingerprinting
For each method on a bean, see exactly which injected dependencies it touches in bytecode. :dep-frequency ranks deps by how many methods use them — count-1 deps are prime extraction candidates. :intra-calls? adds which siblings each method calls; :callers? adds the inverse. Kotlin $default synthetic call variants resolved automatically.
(cg/method-dep-map "adminService")
;; :methods [{:method "getSystemStats"
;; :deps ["authorRepository" "bookRepository" ...]
;; :orchestrator? false} ...]
;; :dep-frequency [{:dep "bookRepository"
;; :used-by-count 2} ...]
;; Who has no external callers? Split :dead from :internal-only
(cg/dead-methods "bookService")
;; {:dead [] :internal-only [{:method "archiveBook"
;; :intra-callers ["adminHelper"]}]
;; :warnings ["2 @EventListener beans detected — ...]}
🎲
Test Data Generation — build valid entities on the fly
Construct realistic, persistable Hibernate entity instances from the REPL — no fixture files, no test annotations, no restart. 54+ heuristic patterns match property names and types to net.datafaker providers (person, address, financial, content, and more). jakarta.validation.constraints annotations are respected at generation time — @Min/@Max clamp numeric ranges, @Email ensures valid addresses, @Size clamps string length — and overrides that violate @NotNull or @Min/@Max throw immediately with a clear message instead of a cryptic Hibernate error at flush time. Lookup tables (like Genre) are fetched from the DB to avoid unique-constraint violations. Use build-test-recipe to capture every generated value with its Java type and repo bean name — the exact seed for @BeforeEach setup and assertions.
;; Simple entity — all scalar fields filled with realistic data
(faker/build-entity "Author")
;; Capture full graph as typed recipe — seed for integration tests
(faker/build-test-recipe "Review")
;; => {:Review {:repo "reviewRepository"
;; :fields {:rating {:type "short" :value 5} …}}}
;; Speculative: get a real id, call your service, roll everything back
(let [review (faker/build-entity "Review"
{:auto-deps? true :persist? true :rollback? true})]
(.computeRating (lw/bean "ratingService") (.getId review)))
🗂️
Repository → Entity Mapping — no convention guessing
Spring Data repository names follow a convention that breaks down with custom names, multi-module projects, or unfamiliar codebases. repo-entity and all-repo-entities give the authoritative answer at runtime — entity class, fully-qualified name, and ID type — in one call. No source reading, no guessing.
;; What entity does this repo manage?
(lw/repo-entity "bookRepository")
;; => {:bean "bookRepository" :entity "Book"
;; :entity-fqn "com.example.domain.Book" :id-type "Long"}
;; Full repo → entity map for the whole application
(lw/all-repo-entities)
;; => [{:bean "authorRepository" :entity "Author" …}
;; {:bean "bookRepository" :entity "Book" …} …]