C4-PlantUML icon indicating copy to clipboard operation
C4-PlantUML copied to clipboard

Java OutOfMemoryError with some Sequence diagrams

Open SlavaVedernikov opened this issue 10 months ago • 4 comments

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.

image

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 (?)

SlavaVedernikov avatar Apr 23 '24 17:04 SlavaVedernikov

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

kirchsth avatar Apr 27 '24 13:04 kirchsth

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

kirchsth avatar Apr 27 '24 15:04 kirchsth

Hi @kirchsth

Thank you for investigating this. I think I'll stick with !pragma teoz false for now.

Thanks, Slava

SlavaVedernikov avatar May 01 '24 21:05 SlavaVedernikov

Not sure yet, but we might might want to add "does not always play well with teoz" to the docs "somewhere".

Potherca avatar May 03 '24 07:05 Potherca

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!

arnaudroques avatar May 17 '24 21:05 arnaudroques

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.

The-Lum avatar May 26 '24 18:05 The-Lum