Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java OutOfMemoryError with some Sequence diagrams #348

Open
SlavaVedernikov opened this issue Apr 23, 2024 · 5 comments
Open

Java OutOfMemoryError with some Sequence diagrams #348

SlavaVedernikov opened this issue Apr 23, 2024 · 5 comments
Labels
forum/plantuml Issue reported to forum/plantuml, wait for final solution

Comments

@SlavaVedernikov
Copy link

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

@kirchsth
Copy link
Contributor

kirchsth commented Apr 27, 2024

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
Copy link
Contributor

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 kirchsth added the forum/plantuml Issue reported to forum/plantuml, wait for final solution label Apr 29, 2024
@SlavaVedernikov
Copy link
Author

Hi @kirchsth

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

Thanks,
Slava

@Potherca
Copy link
Member

Potherca commented May 3, 2024

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

@arnaudroques
Copy link

The root cause of this issue has been identified: plantuml/plantuml#1777 (comment)

We will commit the fix in the incoming days.
Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
forum/plantuml Issue reported to forum/plantuml, wait for final solution
Projects
None yet
Development

No branches or pull requests

4 participants