Multi-language documentation snippets (Java, Kotlin, Groovy, Python) - #2107
graemerocher wants to merge 2 commits into
Conversation
6d707f5 to
325dc1e
Compare
Every application-code sample of the user guide is now a `snippet::` macro backed by compiled and tested sources in Java, Kotlin, Groovy and Python: - new `test-suite`, `test-suite-groovy`, `test-suite-kotlin` and `test-suite-python` projects (convention plugin `io.micronaut.build.internal.sql-test-suite`) hosting the hibernate (@PersistenceContext injection, entity scan, compile-time proxies, @EmbeddedId) and jdbc (multiple data sources, @transactional, runtime password rotation) examples against an in-memory H2 database - new `tests/mybatis-python` project for the existing `project-base="tests/mybatis"` snippet - the 13 inline Java blocks and the stale Groovy `annotationProcessor` block are replaced by snippets; hand-written dependency blocks use the `dependency:` macro - Python CI workflow (`./gradlew pythonCheck -Ppython-ci`) synced from the project template TODO(python-docs): requires micronaut-build 8.1.1 (micronaut-projects/micronaut-build#940);
Bump micronaut-core to 5.2.3 and micronaut-build to 8.1.2, pass the allowReflection option to the Python compiler so that Hibernate maps the Python entities, and re-enable the entity scan and embedded id tests. The two tests that read the id Hibernate assigns on persist stay disabled.
325dc1e to
76d9dec
Compare
dstepanov
left a comment
There was a problem hiding this comment.
Review: multi-language docs port (pyronaut#139)
Verdict:
Summary: the PR bumps micronaut-build to 8.1.2 and core to 5.2.3. There are no production (src/main) changes. Deleted docs lines are only inline blocks replaced by snippets, and their prose moved into callouts; the long DbPasswordRefresher comments were kept. The two @Disabled Python tests match tracked item (d) in the "re-verifying against 5.2.3" section of the issue (Java-side id write-back on persist), so they are not stale. The -Amicronaut.introspection.allowReflection compiler arg matches the core#13252 follow-up. CI is skipped because the PR is a draft.
Findings:
- [medium] src/main/docs/guide/hibernate/hibernate-proxies.adoc:24, hibernate-graalvm.adoc:37 — the Groovy tab of
snippet::…proxies.Ownershows a@GenerateProxyGroovy entity. That sample is known not to work: test-suite-groovy/…/proxies/CompileTimeProxiesSpec.groovy:12 is@Ignored because inject-groovy skips$-prefixed methods, and loading the lazy association throwsAbstractMethodError. Groovy users get a sample that fails at runtime with no warning. Either add a[.lang-groovy]NOTE or render Owner/Pet withlanguages="java,kotlin,python"until the core fix lands. - [low] test-suite/src/test/java/io/micronaut/docs/jdbc/refresh/DbPasswordRefresher.java:21-30 (and the Kotlin/Groovy/Python equivalents) — the published sample now injects the test-only
DbSecretStoreand delegatesgetSecretDbPassword()to it. The guide never introducesDbSecretStore, so readers see an unknown type in the constructor. Keep the store out of theclazztag (for example, leavegetSecretDbPassword()as a documented stub) or add a sentence to the guide. - [low] tests/mybatis-{java,groovy,kotlin}/…/CustomConfigurationCustomizer.*:17 —
setMapUnderscoreToCamelCase(true)was added to the rendered MyBatis customizer sample in all languages only so the Python test has something to assert. The PR body explains it, but it changes what the documented example does. Acceptable; just flagging the behaviour change. - [low] .github/workflows/python.yml — missing the
python/**,python-*stacked-branch targets of the current template (#794).
dstepanov
left a comment
There was a problem hiding this comment.
Approving — the findings in my previous review are minor.
|



Every application-code sample of the user guide is now a
snippet::macro backed by compiled and tested sources in Java, Kotlin, Groovy and Python (the Python compiler), and every dependency uses thedependency:macro so it renders Gradle, Maven and the Python compiler tabs.Part of the multi-language documentation effort built on micronaut-projects/micronaut-build#939.
Important
Requires micronaut-build 8.1.2 (
io.micronaut.build.internal.pythonplugin, Pythondependency:rendering,micronautBuild.python.compilerArgs) and micronaut-core 5.2.3 (the Python compiler and runtime fixes the Hibernate samples rely on); both are released and pinned by this PR.What was ported
New projects:
test-suite(JUnit 5),test-suite-groovy(Spock),test-suite-kotlin(KSP, JUnit 5),test-suite-python(the Python compiler, JUnit 5), sharing theio.micronaut.build.internal.sql-test-suiteconvention (hibernate-jpa + jdbc-hikari + data-tx-hibernate + H2, no Docker), plustests/mybatis-pythonnext to the existingtests/mybatis-{java,groovy,kotlin}.[source,java]@PersistenceContext+ stale[source,groovy]annotationProcessor "jakarta.persistence:jakarta.persistence-api:2.2"io.micronaut.docs.hibernate.session.BookRepository@Introspected(packages="foo.bar")io.micronaut.docs.hibernate.entityscan.ApplicationPet/Ownerio.micronaut.docs.hibernate.proxies.Pet,Owner@Introspected(packages),Owner,Pet,OrderId,Orderio.micronaut.docs.hibernate.graalvm.OrderId,Order@Inject DataSource/@Named("warehouse")io.micronaut.docs.jdbc.multiple.InventoryService@Transactional void saveBook(Book)io.micronaut.docs.jdbc.transactions.BookRepositoryDbPasswordRefreshervariantsio.micronaut.docs.jdbc.refresh.DbPasswordRefresher,io.micronaut.docs.jdbc.refreshdiff.DbPasswordRefresherproject-base="tests/mybatis")tests/mybatis-pythonaddedimplementation("org.jdbi:jdbi3-sqlobject")dependency:jdbi3-sqlobject[groupId="org.jdbi"]13 inline Java blocks + 1 Groovy build block converted; 14
snippet::macros × 4 languages; 28dependency:macros render a the Python compiler tab.Documentation fixes found while making the samples compile and pass:
@Introspected(packages = "...")alone no longer compiles ("When specifying 'packages' you must also specify 'includedAnnotations'"); the sample now usesincludedAnnotations = Entity.class.jakarta.transaction.Transactionalonly works withmicronaut-data-processoron the annotation processor path; the transactions section now says so (dependency:macro). A package-privatevoid saveBook(Book)is not intercepted; the sample method is public.annotationProcessorpath (removed the stalejakarta.persistence-api:2.2instruction).DataSourceis transaction aware: connections must be obtained inside a transactional method (the multiple data sources sample shows@Transactional("warehouse")).CustomConfigurationCustomizer(MyBatis) also tunes a setting (mapUnderscoreToCamelCase) so the Python suite, which cannot declare MyBatis mapper interfaces, has something to assert.Not ported (and why)
jasync-client.adoc,vertxmysqlclient.adoc,vertxpgclient.adoc: the[source,groovy]blocksinclude::fragments of the modules' own Testcontainers specs (JasyncSpec,MySQLClientSpec,PgClientSpec) which need a live PostgreSQL/MySQL (Docker). They stay as Groovy includes of tested code.jooq-graalvm.adoc[source,groovy]: jOOQ Gradle plugin configuration (build file, not application code).@DisabledwithTODO(python)and listed intest-suite-python/src/test/python/micronaut/docs/DISABLED_TESTS.md:hibernate.session.BookRepositoryTestandhibernate.proxies.CompileTimeProxiesTest. The Python entities are plain@Entityclasses and Hibernate maps them (the suite passes-Amicronaut.introspection.allowReflection=micronaut.docs.hibernate.*to the Python compiler so the generated classes carry the JPA annotations), but the id Hibernate assigns onentity_manager.persist(book)is set on the Java wrapper of the Python object and not written back to it, sobook.idstaysNonein the sample'ssave.hibernate.entityscan.EntityScanTestandhibernate.graalvm.EmbeddedIdTestpass; the JDBC and MyBatis Python tests pass.@Ignore:hibernate.proxies.CompileTimeProxiesSpec-@GenerateProxyon a Groovy entity produces a$Owner$Interceptedproxy withoutIntroducedHibernateProxy.$registerInterceptor(inject-groovy'sGroovyClassElementskips$-prefixed methods), so loading the lazy association throwsAbstractMethodError(micronaut-core issue; Java and Kotlin work).Verification
Without
-Ppython-cithe Python sources are compiled but theirTesttasks are skipped (regular CI);.github/workflows/python.ymlis the project-template workflow that runs them on GraalVM.