C4-PlantUML
C4-PlantUML copied to clipboard
Java OutOfMemoryError with some Sequence diagrams
I'm generating C4-PlantUML diagrams as output from my own framework, and it works great in general. thank you.
I'm having issues with some Sequence diagrams though. Java throws an OutOfMemoryError.
Here is an example of the Sequence diagram that does not render.
@startuml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Sequence.puml
title Order Api - Api - Order Controller - Create Order - C4 Sequence - Component level
System_Ext(C4InterFlow.SoftwareSystems.ExternalSystem, "External", "")
System_Boundary(OrderApi, "Order Api")
Container_Boundary(OrderApi.Containers.Api, "Api")
Component(OrderApi.Containers.Api.Components.OrderController, "Order Controller", "", "")
Boundary_End()
Container_Boundary(OrderApi.Containers.Data, "Data")
Component(OrderApi.Containers.Data.Components.OrderDbContext, "Order Db Context", "", "")
Boundary_End()
Container_Boundary(OrderApi.Containers.Application, "Application")
Component(OrderApi.Containers.Application.Components.OrderService, "Order Service", "", "")
Component(OrderApi.Containers.Application.Components.DistributedLockProvider, "Distributed Lock Provider", "", "")
Component(OrderApi.Containers.Application.Components.UserAuditLogService, "User Audit Log Service", "", "")
Boundary_End()
Container_Boundary(OrderApi.Containers.Integration, "Integration")
Component(OrderApi.Containers.Integration.Components.InfinaProxy, "Infina Proxy", "", "")
Component(OrderApi.Containers.Integration.Components.UserAuditLogApiProxy, "User Audit Log Api Proxy", "", "")
Boundary_End()
Boundary_End()
Rel(C4InterFlow.SoftwareSystems.ExternalSystem, OrderApi.Containers.Api.Components.OrderController, "Create Order")
group Create Order
alt request.IsInternalOrder
Rel(OrderApi.Containers.Api.Components.OrderController, OrderApi.Containers.Api.Components.OrderController, "Create Internal Order")
group Create Internal Order
alt request.Side == OrderSide.Buy
Rel(OrderApi.Containers.Api.Components.OrderController, OrderApi.Containers.Api.Components.OrderController, "Calculate Fee Amount")
end
Rel(OrderApi.Containers.Api.Components.OrderController, OrderApi.Containers.Data.Components.OrderDbContext, "Orders Add")
Rel(OrderApi.Containers.Api.Components.OrderController, OrderApi.Containers.Data.Components.OrderDbContext, "Outbox Messages Add")
Rel(OrderApi.Containers.Api.Components.OrderController, OrderApi.Containers.Api.Components.OrderController, "Retun (response)")
end
else
Rel(OrderApi.Containers.Api.Components.OrderController, OrderApi.Containers.Application.Components.OrderService, "Create Order")
group Create Order
Rel(OrderApi.Containers.Application.Components.OrderService, OrderApi.Containers.Application.Components.DistributedLockProvider, "Try Acquire Lock Async")
alt handle != null
Rel(OrderApi.Containers.Application.Components.OrderService, OrderApi.Containers.Application.Components.OrderService, "Map Channel To Infina Programme Name")
Rel(OrderApi.Containers.Application.Components.OrderService, OrderApi.Containers.Application.Components.OrderService, "Map Client Id To Infina Platform Name")
Rel(OrderApi.Containers.Application.Components.OrderService, OrderApi.Containers.Integration.Components.InfinaProxy, "Create Order")
group Create Order
Rel(OrderApi.Containers.Integration.Components.InfinaProxy, OrderApi.Containers.Integration.Components.InfinaProxy, "Retun (proxyResponse)")
end
alt apiResponse.HasError
Rel(OrderApi.Containers.Application.Components.OrderService, OrderApi.Containers.Application.Components.OrderService, "Throw Exception Create Order Failed")
group Throw Exception Create Order Failed
Rel(OrderApi.Containers.Application.Components.OrderService, OrderApi.Containers.Application.Components.OrderService, "Get Problem Details Exception By Infina Oms Error")
group Get Problem Details Exception By Infina Oms Error
Rel(OrderApi.Containers.Application.Components.OrderService, OrderApi.Containers.Application.Components.OrderService, "Extract Error Code From Infina Oms Error Message")
alt match.Success
alt int.TryParse(errorCodeMatch.Value, out int code)
Rel(OrderApi.Containers.Application.Components.OrderService, OrderApi.Containers.Application.Components.OrderService, "Retun (code)")
end
end
Rel(OrderApi.Containers.Application.Components.OrderService, OrderApi.Containers.Application.Components.OrderService, "Retun (problem)")
end
Rel(OrderApi.Containers.Application.Components.OrderService, OrderApi.Containers.Application.Components.OrderService, "Exception (ProblemDetailsException)")
end
end
Rel(OrderApi.Containers.Application.Components.OrderService, OrderApi.Containers.Application.Components.OrderService, "Send Order Created Log To User Audit Log")
group Send Order Created Log To User Audit Log
Rel(OrderApi.Containers.Application.Components.OrderService, OrderApi.Containers.Application.Components.OrderService, "Get Order Side")
Rel(OrderApi.Containers.Application.Components.OrderService, OrderApi.Containers.Application.Components.OrderService, "Get Order Type")
alt request.Type == OrderType.Limit
Rel(OrderApi.Containers.Application.Components.OrderService, OrderApi.Containers.Application.Components.UserAuditLogService, "Send User Audit Log")
group Send User Audit Log
Rel(OrderApi.Containers.Application.Components.UserAuditLogService, OrderApi.Containers.Application.Components.UserAuditLogService, "Get Async Fallback Policy")
group Get Async Fallback Policy
Rel(OrderApi.Containers.Application.Components.UserAuditLogService, OrderApi.Containers.Application.Components.UserAuditLogService, "Create Outbox Message")
group Create Outbox Message
Rel(OrderApi.Containers.Application.Components.UserAuditLogService, OrderApi.Containers.Data.Components.OrderDbContext, "Outbox Messages Add")
end
Rel(OrderApi.Containers.Application.Components.UserAuditLogService, OrderApi.Containers.Application.Components.UserAuditLogService, "Retun (fallback)")
end
Rel(OrderApi.Containers.Application.Components.UserAuditLogService, OrderApi.Containers.Application.Components.UserAuditLogService, "Get Async Retry Policy")
group Get Async Retry Policy
Rel(OrderApi.Containers.Application.Components.UserAuditLogService, OrderApi.Containers.Application.Components.UserAuditLogService, "Retun (retryPolicy)")
end
Rel(OrderApi.Containers.Application.Components.UserAuditLogService, OrderApi.Containers.Application.Components.UserAuditLogService, "Get Async Circuit Breaker Policy")
group Get Async Circuit Breaker Policy
Rel(OrderApi.Containers.Application.Components.UserAuditLogService, OrderApi.Containers.Application.Components.UserAuditLogService, "Retun (breaker)")
end
Rel(OrderApi.Containers.Application.Components.UserAuditLogService, OrderApi.Containers.Integration.Components.UserAuditLogApiProxy, "Create User Audit Log")
group Create User Audit Log
alt responseMessage.IsSuccessStatusCode
Rel(OrderApi.Containers.Integration.Components.UserAuditLogApiProxy, OrderApi.Containers.Integration.Components.UserAuditLogApiProxy, "Retun (proxyResponse)")
end
Rel(OrderApi.Containers.Integration.Components.UserAuditLogApiProxy, OrderApi.Containers.Integration.Components.UserAuditLogApiProxy, "Retun (proxyResponse)")
end
end
Rel(OrderApi.Containers.Application.Components.OrderService, OrderApi.Containers.Application.Components.OrderService, "Retun")
end
Rel(OrderApi.Containers.Application.Components.OrderService, OrderApi.Containers.Application.Components.UserAuditLogService, "Send User Audit Log")
group Send User Audit Log
Rel(OrderApi.Containers.Application.Components.UserAuditLogService, OrderApi.Containers.Application.Components.UserAuditLogService, "Get Async Fallback Policy")
group Get Async Fallback Policy
Rel(OrderApi.Containers.Application.Components.UserAuditLogService, OrderApi.Containers.Application.Components.UserAuditLogService, "Create Outbox Message")
group Create Outbox Message
Rel(OrderApi.Containers.Application.Components.UserAuditLogService, OrderApi.Containers.Data.Components.OrderDbContext, "Outbox Messages Add")
end
Rel(OrderApi.Containers.Application.Components.UserAuditLogService, OrderApi.Containers.Application.Components.UserAuditLogService, "Retun (fallback)")
end
Rel(OrderApi.Containers.Application.Components.UserAuditLogService, OrderApi.Containers.Application.Components.UserAuditLogService, "Get Async Retry Policy")
group Get Async Retry Policy
Rel(OrderApi.Containers.Application.Components.UserAuditLogService, OrderApi.Containers.Application.Components.UserAuditLogService, "Retun (retryPolicy)")
end
Rel(OrderApi.Containers.Application.Components.UserAuditLogService, OrderApi.Containers.Application.Components.UserAuditLogService, "Get Async Circuit Breaker Policy")
group Get Async Circuit Breaker Policy
Rel(OrderApi.Containers.Application.Components.UserAuditLogService, OrderApi.Containers.Application.Components.UserAuditLogService, "Retun (breaker)")
end
Rel(OrderApi.Containers.Application.Components.UserAuditLogService, OrderApi.Containers.Integration.Components.UserAuditLogApiProxy, "Create User Audit Log")
group Create User Audit Log
alt responseMessage.IsSuccessStatusCode
Rel(OrderApi.Containers.Integration.Components.UserAuditLogApiProxy, OrderApi.Containers.Integration.Components.UserAuditLogApiProxy, "Retun (proxyResponse)")
end
Rel(OrderApi.Containers.Integration.Components.UserAuditLogApiProxy, OrderApi.Containers.Integration.Components.UserAuditLogApiProxy, "Retun (proxyResponse)")
end
end
end
Rel(OrderApi.Containers.Application.Components.OrderService, OrderApi.Containers.Application.Components.OrderService, "Retun (response)")
else
Rel(OrderApi.Containers.Application.Components.OrderService, OrderApi.Containers.Application.Components.OrderService, "Exception (Exception)")
end
end
end
Rel(OrderApi.Containers.Api.Components.OrderController, OrderApi.Containers.Api.Components.OrderController, "Retun (Created)")
end
@enduml
...and here is the same diagram written just in PlantUML, which renders successfully.
@startuml
title Order Api - Api - Order Controller - Delete Order - Sequence - Component level
participant "External" as C4InterFlow.SoftwareSystems.ExternalSystem
box "Order Api" #White
box "Api" #White
participant "Order Controller" as OrderApi.Containers.Api.Components.OrderController
end box
box "Application" #White
participant "Order Service" as OrderApi.Containers.Application.Components.OrderService
participant "Distributed Lock Provider" as OrderApi.Containers.Application.Components.DistributedLockProvider
participant "User Audit Log Service" as OrderApi.Containers.Application.Components.UserAuditLogService
end box
box "Integration" #White
participant "Infina Proxy" as OrderApi.Containers.Integration.Components.InfinaProxy
participant "User Audit Log Api Proxy" as OrderApi.Containers.Integration.Components.UserAuditLogApiProxy
end box
box "Data" #White
participant "Order Db Context" as OrderApi.Containers.Data.Components.OrderDbContext
end box
end box
C4InterFlow.SoftwareSystems.ExternalSystem -> OrderApi.Containers.Api.Components.OrderController : Delete Order
group Delete Order
OrderApi.Containers.Api.Components.OrderController -> OrderApi.Containers.Application.Components.OrderService : Delete Order
group Delete Order
OrderApi.Containers.Application.Components.OrderService -> OrderApi.Containers.Application.Components.DistributedLockProvider : Try Acquire Lock Async
alt handle != null
OrderApi.Containers.Application.Components.OrderService -> OrderApi.Containers.Integration.Components.InfinaProxy : Get Order
group Get Order
alt responseMessage.IsSuccessStatusCode
OrderApi.Containers.Integration.Components.InfinaProxy -> OrderApi.Containers.Integration.Components.InfinaProxy : Retun (proxyResponse)
end
OrderApi.Containers.Integration.Components.InfinaProxy -> OrderApi.Containers.Integration.Components.InfinaProxy : Retun (proxyResponse)
end
OrderApi.Containers.Application.Components.OrderService -> OrderApi.Containers.Application.Components.OrderService : Throw Exception If Get Order Failed While Delete Order
group Throw Exception If Get Order Failed While Delete Order
alt !proxyResponse.HasError
OrderApi.Containers.Application.Components.OrderService -> OrderApi.Containers.Application.Components.OrderService : Retun
end
alt proxyResponse.ProblemDetails.Status == StatusCodes.Status404NotFound
OrderApi.Containers.Application.Components.OrderService -> OrderApi.Containers.Application.Components.OrderService : Exception (ProblemDetailsException)
end
OrderApi.Containers.Application.Components.OrderService -> OrderApi.Containers.Application.Components.OrderService : Get Problem Details Exception By Infina Oms Error
group Get Problem Details Exception By Infina Oms Error
OrderApi.Containers.Application.Components.OrderService -> OrderApi.Containers.Application.Components.OrderService : Extract Error Code From Infina Oms Error Message
alt match.Success
alt int.TryParse(errorCodeMatch.Value, out int code)
OrderApi.Containers.Application.Components.OrderService -> OrderApi.Containers.Application.Components.OrderService : Retun (code)
end
end
OrderApi.Containers.Application.Components.OrderService -> OrderApi.Containers.Application.Components.OrderService : Retun (problem)
end
OrderApi.Containers.Application.Components.OrderService -> OrderApi.Containers.Application.Components.OrderService : Exception (ProblemDetailsException)
end
OrderApi.Containers.Application.Components.OrderService -> OrderApi.Containers.Application.Components.OrderService : Map Client Id To Infina Platform Name
OrderApi.Containers.Application.Components.OrderService -> OrderApi.Containers.Application.Components.OrderService : Map Channel To Infina Programme Name
OrderApi.Containers.Application.Components.OrderService -> OrderApi.Containers.Integration.Components.InfinaProxy : Delete Order
group Delete Order
alt responseMessage.IsSuccessStatusCode
OrderApi.Containers.Integration.Components.InfinaProxy -> OrderApi.Containers.Integration.Components.InfinaProxy : Retun (proxyResponse)
end
OrderApi.Containers.Integration.Components.InfinaProxy -> OrderApi.Containers.Integration.Components.InfinaProxy : Retun (proxyResponse)
end
alt response.HasError
OrderApi.Containers.Application.Components.OrderService -> OrderApi.Containers.Application.Components.OrderService : Throw Delete Order Error Exception
group Throw Delete Order Error Exception
OrderApi.Containers.Application.Components.OrderService -> OrderApi.Containers.Application.Components.OrderService : Get Problem Details Exception By Infina Oms Error
group Get Problem Details Exception By Infina Oms Error
OrderApi.Containers.Application.Components.OrderService -> OrderApi.Containers.Application.Components.OrderService : Extract Error Code From Infina Oms Error Message
alt match.Success
alt int.TryParse(errorCodeMatch.Value, out int code)
OrderApi.Containers.Application.Components.OrderService -> OrderApi.Containers.Application.Components.OrderService : Retun (code)
end
end
OrderApi.Containers.Application.Components.OrderService -> OrderApi.Containers.Application.Components.OrderService : Retun (problem)
end
OrderApi.Containers.Application.Components.OrderService -> OrderApi.Containers.Application.Components.OrderService : Exception (ProblemDetailsException)
end
end
OrderApi.Containers.Application.Components.OrderService -> OrderApi.Containers.Application.Components.OrderService : Send Order Cancelled Log To User Audit Log
group Send Order Cancelled Log To User Audit Log
OrderApi.Containers.Application.Components.OrderService -> OrderApi.Containers.Application.Components.OrderService : Get Order Side
OrderApi.Containers.Application.Components.OrderService -> OrderApi.Containers.Application.Components.OrderService : Get Order Type
OrderApi.Containers.Application.Components.OrderService -> OrderApi.Containers.Application.Components.UserAuditLogService : Send User Audit Log
group Send User Audit Log
OrderApi.Containers.Application.Components.UserAuditLogService -> OrderApi.Containers.Application.Components.UserAuditLogService : Get Async Fallback Policy
group Get Async Fallback Policy
OrderApi.Containers.Application.Components.UserAuditLogService -> OrderApi.Containers.Application.Components.UserAuditLogService : Create Outbox Message
group Create Outbox Message
OrderApi.Containers.Application.Components.UserAuditLogService -> OrderApi.Containers.Data.Components.OrderDbContext : Outbox Messages Add
end
OrderApi.Containers.Application.Components.UserAuditLogService -> OrderApi.Containers.Application.Components.UserAuditLogService : Retun (fallback)
end
OrderApi.Containers.Application.Components.UserAuditLogService -> OrderApi.Containers.Application.Components.UserAuditLogService : Get Async Retry Policy
group Get Async Retry Policy
OrderApi.Containers.Application.Components.UserAuditLogService -> OrderApi.Containers.Application.Components.UserAuditLogService : Retun (retryPolicy)
end
OrderApi.Containers.Application.Components.UserAuditLogService -> OrderApi.Containers.Application.Components.UserAuditLogService : Get Async Circuit Breaker Policy
group Get Async Circuit Breaker Policy
OrderApi.Containers.Application.Components.UserAuditLogService -> OrderApi.Containers.Application.Components.UserAuditLogService : Retun (breaker)
end
OrderApi.Containers.Application.Components.UserAuditLogService -> OrderApi.Containers.Integration.Components.UserAuditLogApiProxy : Create User Audit Log
group Create User Audit Log
alt responseMessage.IsSuccessStatusCode
OrderApi.Containers.Integration.Components.UserAuditLogApiProxy -> OrderApi.Containers.Integration.Components.UserAuditLogApiProxy : Retun (proxyResponse)
end
OrderApi.Containers.Integration.Components.UserAuditLogApiProxy -> OrderApi.Containers.Integration.Components.UserAuditLogApiProxy : Retun (proxyResponse)
end
end
end
else
OrderApi.Containers.Application.Components.OrderService -> OrderApi.Containers.Application.Components.OrderService : Exception (Exception)
end
end
OrderApi.Containers.Api.Components.OrderController -> OrderApi.Containers.Api.Components.OrderController : Retun (Accepted)
end
@enduml
Please let me know if I'm doing something unexpected/wrong etc. ...or maybe it's a bug (?)
Hi @SlavaVedernikov
I found the problem. It is !pragma teoz true
. I use the !pragma teoz true
that the sequence diagram supports multiple boundaries too.
E.g. in your case with the !pragma teoz true
(default of C4_Squenece.puml) your components/participants look like below (incl. "Order API" boundary)
Without teoz (or in our case an additional !pragma teoz false
) they look like below ("Order API" boundary is lost).
If you don't need the overall boundary then you can simply fix it with an !pragma teoz false
line after the include.
@startuml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Sequence.puml
'following fixes your memory problem
!pragma teoz false
Best regards Helmut
PS.: I entered an issue in forum, but I'm not sure if we can get a fix
Hi @SlavaVedernikov,
a second alternative could be that you increase the available memory, e.g. start the tool with 8GB like
java -Xms8192m -Xmx8192m -jar plantuml.jar "YOUR_FILE.puml"
but then the build is very slow (I checked it on my machine and the C4-Stdlib version requires ~1min40sec instead of ~5sec if you build it without teoz)
BR Helmut
Hi @kirchsth
Thank you for investigating this.
I think I'll stick with !pragma teoz false
for now.
Thanks, Slava
Not sure yet, but we might might want to add "does not always play well with teoz" to the docs "somewhere".
The root cause of this issue has been identified: https://github.com/plantuml/plantuml/pull/1777#issuecomment-2118408574
We will commit the fix in the incoming days. Thanks!
Hi all,
FYI: This is now fixed on PlantUML V1.2024.5.
- Thanks @SlavaVedernikov for the report.
- Thanks PlantUML team and @arnaudroques for your work.
Regards.