question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Documenter fails when using functional endpoints (i.e. RouterFunction beans)

See original GitHub issue

Hello,

It seems moduliths-docs doesn’t support projects leveraging functional web endpoints registration - be it either WebMvc.fn or WebFlux.fn (fails for both, checked myself).

Project setup: Java 11 + Kotlin (checked also Java 8) Spring Boot 2.4.1 (checked also using Spring Boot 2.3.7) Moduliths 1.1.0-M1 (checked also current main branch)

Test body (in Kotlin):

class DocumentingTest {

    @Test
    @Throws(IOException::class)
    fun verifyModularity() {
        val modules: Modules = Modules.of(ModulithsDemoApplication::class.java)

        modules.verify()

        // Generate documentation
        val documenter = Documenter(modules)
        val options: Options = Options.defaults() //
            .withExclusions { module -> module.getName().matches(".*core|.*support".toRegex()) }

        // Write overall diagram
        // FIXME This fails if RouterFunction is registered as a bean :(
        documenter.writeModulesAsPlantUml(options)

Stack-trace starting from the test-run:

java.lang.NullPointerException: Method may not be called before construction of hierarchy is complete

	at com.tngtech.archunit.thirdparty.com.google.common.base.Preconditions.checkNotNull(Preconditions.java:787)
	at com.tngtech.archunit.core.domain.JavaClass.getAllMethods(JavaClass.java:788)
	at org.moduliths.model.Module$ModuleDependency.fromMethodsOf(Module.java:523)
	at org.moduliths.model.Module$ModuleDependency.fromType(Module.java:499)
	at org.moduliths.model.Module.lambda$getDirectModuleDependencies$16(Module.java:361)
	at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:271)
	at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1654)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
	at org.moduliths.docs.Documenter.addDependencies(Documenter.java:266)
	at org.moduliths.docs.Documenter.lambda$getComponents$1(Documenter.java:126)
	at java.base/java.util.HashMap.forEach(HashMap.java:1336)
	at org.moduliths.docs.Documenter.getComponents(Documenter.java:126)
	at org.moduliths.docs.Documenter.lambda$addComponentsToView$13(Documenter.java:288)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
	at java.base/java.util.HashMap$ValueSpliterator.forEachRemaining(HashMap.java:1675)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
	at org.moduliths.docs.Documenter.addComponentsToView(Documenter.java:289)
	at org.moduliths.docs.Documenter.createPlantUml(Documenter.java:370)
	at org.moduliths.docs.Documenter.writeModulesAsPlantUml(Documenter.java:145)
	at com.example.modulithsdemo.DocumentingTest.verifyModularity(DocumentingTest.kt:28)

I tried adding to org.springframework.web.servlet.function and org.springframework.web.reactive.function to org.moduliths.model.Modules#FRAMEWORK_PACKAGES, but this causes some further NPEs while rendering AsciiDoctor.

P.S. Thanks a lot (!) for this project and efforts put here, I think this represents a wide gap in current Java toolset.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5

github_iconTop GitHub Comments

1reaction
odrotbohmcommented, Feb 15, 2021

This is in place now in the current snapshots. The sample project provided builds fine with those used.

1reaction
odrotbohmcommented, Feb 15, 2021

Looks like this is caused by a special arrangement in declared and actually used types within ArchUnit. @codecholeric has a proposed fix for that in TNG/ArchUnit#530 but a workaround would be to add org.springframework.web.reactive into the framework packages to be explicitly scanned.

The aforementioned improvement in ArchUnit should actually make our explicit list of framework packages to include in the scanning obsolete. I’ll create a separate issue for that.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Provide a WebMvc.fn / WebFlux.fn functional DSL #891 - GitHub
I am not an OpenAPI guru, but I tend to think that programmatic APIs and method references could allow springdoc-openapi to provide an...
Read more >
Web on Reactive Stack - Spring
At the programming-model level, Java 8 enabled Spring WebFlux to offer functional web endpoints alongside annotated controllers.
Read more >
Introduction to the Functional Web Framework in Spring 5
First, we need to create routes using RouterFunction to publish and consume our reactive streams of Employees. Routes are registered as Spring ...
Read more >
spring-projects/spring-boot - Gitter
i have a custom WebFluxResponseStatusExceptionHandler that acts as a fault barrier. Works great when using Webflux controllers. I'm trying to get it to...
Read more >
Spring Webflux - Functional Endpoints - Object Partners
This post will look at how to set up a simple router and get global error handling in place using the new webflux.fn...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found