avisi-cloud / structurizr-site-generatr

Static site generator for architecture models created with Structurizr DSL
https://avisi-cloud.github.io/structurizr-site-generatr/
Apache License 2.0
230 stars 36 forks source link

Feature Request: Support for `image` views or option to ignore such views #625

Open hgross opened 1 month ago

hgross commented 1 month ago

Structurizr supports to integrate with PlantUML (or other plugins like Mermaid) by defining an image-view (see structurizr docs).

Do you have any plans to support or add an option to ignore those image-views? At this moment, the generate-site command will fail when such a view is defined:


views {
    properties {
        "plantuml.url" "http://localhost:8888"
        "plantuml.format" "svg" // or "png"
    }

    image scope "plantuml-my-state-machine" {
        plantuml "model/state-machine.puml"
        title "[State] Some State Machine"
    }

    ...
}
Exception in thread "main" java.lang.IllegalStateException: java.lang.IllegalStateException: View [State] Some State Machine has a non-exportable type
        at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(Unknown Source)
        at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Unknown Source)
        at java.base/java.lang.reflect.Constructor.newInstance(Unknown Source)
        at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(Unknown Source)
        at java.base/java.util.concurrent.ForkJoinTask.reportException(Unknown Source)
        at java.base/java.util.concurrent.ForkJoinTask.invoke(Unknown Source)
        at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateParallel(Unknown Source)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateParallel(Unknown Source)
        at java.base/java.util.stream.AbstractPipeline.evaluate(Unknown Source)
        at java.base/java.util.stream.ReferencePipeline.forEach(Unknown Source)
        at java.base/java.util.stream.ReferencePipeline$Head.forEach(Unknown Source)
        at nl.avisi.structurizr.site.generatr.site.SiteGeneratorKt.generateHtmlFiles(SiteGenerator.kt:202)
        at nl.avisi.structurizr.site.generatr.site.SiteGeneratorKt.generateSite(SiteGenerator.kt:87)
        at nl.avisi.structurizr.site.generatr.site.SiteGeneratorKt.generateSite$default(SiteGenerator.kt:67)
        at nl.avisi.structurizr.site.generatr.GenerateSiteCommand.generateSiteForModel(GenerateSiteCommand.kt:131)
        at nl.avisi.structurizr.site.generatr.GenerateSiteCommand.execute(GenerateSiteCommand.kt:73)
        at kotlinx.cli.ArgParser.parse(ArgParser.kt:657)
        at kotlinx.cli.ArgParser.parse(ArgParser.kt:530)
        at nl.avisi.structurizr.site.generatr.AppKt.main(App.kt:13)
Caused by: java.lang.IllegalStateException: View [State] Some State Machine has a non-exportable type
        at nl.avisi.structurizr.site.generatr.site.PlantUmlExporterWithElementLinks.export(PlantUmlExporter.kt:49)
        at nl.avisi.structurizr.site.generatr.site.DiagramGeneratorKt.generatePlantUMLDiagramWithElementLinks(DiagramGenerator.kt:86)
        at nl.avisi.structurizr.site.generatr.site.DiagramGeneratorKt.generateDiagramWithElementLinks(DiagramGenerator.kt:43)
        at nl.avisi.structurizr.site.generatr.site.SiteGeneratorKt.generateSite$lambda$8(SiteGenerator.kt:79)
        at nl.avisi.structurizr.site.generatr.site.model.DiagramViewModel$Companion.forView(DiagramViewModel.kt:26)
        at nl.avisi.structurizr.site.generatr.site.model.ToHtmlKt.transformEmbeddedDiagramElements(ToHtml.kt:171)
        at nl.avisi.structurizr.site.generatr.site.model.ToHtmlKt.markdownToHtml(ToHtml.kt:56)
        at nl.avisi.structurizr.site.generatr.site.model.ToHtmlKt.toHtml(ToHtml.kt:34)
        at nl.avisi.structurizr.site.generatr.site.model.WorkspaceDocumentationSectionPageViewModel.<init>(WorkspaceDocumentationSectionPageViewModel.kt:12)
        at nl.avisi.structurizr.site.generatr.site.SiteGeneratorKt.generateHtmlFiles$lambda$52$lambda$17$lambda$16(SiteGenerator.kt:138)
        at nl.avisi.structurizr.site.generatr.site.SiteGeneratorKt.generateHtmlFiles$lambda$53(SiteGenerator.kt:202)
        at nl.avisi.structurizr.site.generatr.site.SiteGeneratorKt.generateHtmlFiles$lambda$54(SiteGenerator.kt:202)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(Unknown Source)
        at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(Unknown Source)
        at java.base/java.util.stream.AbstractPipeline.copyInto(Unknown Source)
        at java.base/java.util.stream.ForEachOps$ForEachTask.compute(Unknown Source)
        at java.base/java.util.concurrent.CountedCompleter.exec(Unknown Source)
        at java.base/java.util.concurrent.ForkJoinTask.doExec(Unknown Source)
        at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(Unknown Source)
        at java.base/java.util.concurrent.ForkJoinPool.scan(Unknown Source)
        at java.base/java.util.concurrent.ForkJoinPool.runWorker(Unknown Source)
        at java.base/java.util.concurrent.ForkJoinWorkerThread.run(Unknown Source)
qtzar commented 1 month ago

I just tested this and it seems to be working fine. The only difference between what I did and what you have above is that I set the plantUML Generator URL to a real url and not localHost:8888

"plantuml.url" "https://plantuml.com/plantuml"

the localhost:8888 in the documentation is only valid if you have a PlantUML generator running locally on that port.

hgross commented 1 month ago

I have a working backend PlantUML backend running locally. All my PlantUML diagrams are fine in structurizr-lite's structurizr-ui. I am using docker compose to set up the whole thing - like this:

services:
  structurizr:
    image: structurizr/lite
    ports:
      - "8081:8080"
    volumes:
      - ./structurizr:/usr/local/structurizr
    environment:
      - STRUCTURIZR_WORKSPACE_FILENAME=${STRUCTURIZR_WORKSPACE_FILENAME:-model/workspace.dsl}
      - TZ=Europe/Berlin

  plantuml:
    image: plantuml/plantuml-server:tomcat
    ports:
      - "8080:8080"
    environment:
      - PLANTUML_LIMIT_SIZE=24384
      - JAVA_MIN_HEAP_SIZE=64M
      - JAVA_MAX_HEAP_SIZE=4G
      - TZ=Europe/Berlin

I am also using the docker variant to execute generate-site: docker run -it --rm -v ${workspaceFolder}/structurizr:/var/model ghcr.io/avisi-cloud/structurizr-site-generatr generate-site --workspace-file workspace.dsl

Does generatr require direct access to the PlantUML endpoint to work? This would not be the case with my docker-compose setup, since the docker run call would not have access because localhost would point somewhere else without bridging it into the docker-compose network.

The exception message has a non-exportable type does not reveal much of the details.

qtzar commented 1 month ago

yes, this seems to be more of a docker config issue.

You are on the correct line of thought to build out a new network bridge to run all these containers in, give the containers names and then in the view property you should be able to reference the PlantUML container by name instead of localhost.

hgross commented 1 month ago

Ok, I noticed that generate-site in my setup actually works fine with my PlantUML sequence diagrams, but fails (only) with state diagrams. So I can rule out problems with the setup.

It is reprodcuible with this simple plantuml state diagram:

@startuml "my-state-machine"
[*] --> State1
State1 --> [*]
State1 : this is a string
State1 : this is another string

State1 -> State2
State2 --> [*]
@enduml

State Diagram

Can you give this a try in your environment?