PlantUML

Introduction

PlantUML makes it easy to create and maintain software diagrams.

real-world-plantuml.com shows many examples of PlantUML diagrams.

A template/theme is provided as part of DocDac that fits with the overall ReadTheDocs template i.e. blue, white and grey skins for PlantUML objects.

Note

PlantUML is great for software diagrams (class diagrams, sequence diagrams, etc…). But for non-UML diagrams, or for where you want to control the exact layout, auto-generation via PlantUML may not be the way to go.

Using PlantUML

PlantUML source files referenced in rst files are automatically converted to diagrams e.g.

.. uml:: plantuml/examples/state.puml
:align: center
:caption: *State Diagram - without theme*

Tip

To manually convert a PlantUML file:

docker run -u `id -u $USER`:`id -g $USER` -i --rm -v $(pwd):/home/documentation -t  docdac:ubuntu-1.0 java -jar /usr/share/plantuml/plantuml.jar docs/plantuml/examples/state.puml  -o "nostyle"

To manually convert several PlantUML files:

docker run -u `id -u $USER`:`id -g $USER` -i --rm -v $(pwd):/home/documentation -t  docdac:ubuntu-1.0 java -jar /usr/share/plantuml/plantuml.jar -Idocs/plantuml/plantuml_cfg.puml docs/plantuml/examples/*.puml

PlantUML Theme

The default (yellow) PlantUML theme is overridden with a Blue (#BDE3FF and white) theme as specified in plantuml_cfg.puml:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
' https://plantuml-documentation.readthedocs.io/en/latest/formatting/all-skin-params.html
' colour  decoder: https://www.google.com/search?q=hex+color+picker&oq=hex+col&aqs=chrome.0.0l2j69i57j0l3.1975j0j7&sourceid=chrome&ie=UTF-8
' http://plantuml.com/skinparam

skinparam backgroundColor white

skinparam note {
    BackgroundColor #F1FFFF
    BorderColor #2980B9
}

skinparam activity {
    BackgroundColor #BDE3FF
    ArrowColor #2980B9
    BorderColor #2980B9
    StartColor #227BC6
    EndColor #227BC6
    BarColor #227BC6
}

skinparam sequence {
    ArrowColor  #2980B9
    DividerBackgroundColor  #BDE3FF
    GroupBackgroundColor    #BDE3FF
    LifeLineBackgroundColor white
    LifeLineBorderColor #2980B9
    ParticipantBackgroundColor  #BDE3FF
    ParticipantBorderColor  #2980B9
    BoxLineColor    #2980B9
    BoxBackgroundColor  #DDDDDD
}

skinparam componentBackgroundColor    #BDE3FF
skinparam component {
    skinparam componentArrowColor #A80036
    skinparam BorderColor    #A80036
    skinparam InterfaceBackgroundColor   #BDE3FF
    skinparam InterfaceBorderColor   #A80036
}


'for some reason if we put BackgroundColor inside {} it does not work?
skinparam stateBackgroundColor #BDE3FF
skinparam state {
    skinparam BorderColor #2980B9
    skinparam ArrowColor #2980B9
    skinparam StartColor black
    skinparam EndColor   black
}


skinparam stereotype {                  
    skinparam CBackgroundColor  #ADD1B2
    skinparam ABackgroundColor  #A9DCDF
    skinparam IBackgroundColor  #B4A7E5
    skinparam EBackgroundColor  #EB937F
}

'for some reason if we put BackgroundColor inside {} it does not work?
skinparam actorBackgroundColor #BDE3FF
skinparam actor {
    skinparam BorderColor    #A80036
}

skinparam usecase {
    skinparam ArrowColor   #A80036
    skinparam BorderColor  #A80036
}

skinparam class {
    skinparam ArrowColor #A80036
    skinparam BackgroundColor    #BDE3FF
    skinparam BorderColor    #A80036
}


skinparam object {
    skinparam ArrowColor    #A80036
    skinparam BackgroundColor   #BDE3FF
    skinparam BorderColor   #A80036
}


skinparam packageBackgroundColor  #white
skinparam agentBackgroundColor  #BDE3FF
skinparam artifactBackgroundColor  #BDE3FF
skinparam boundaryBackgroundColor  #BDE3FF
skinparam cardBackgroundColor  #BDE3FF
skinparam cloudBackgroundColor  #BDE3FF
skinparam controlBackgroundColor  #BDE3FF
skinparam databaseBackgroundColor  #BDE3FF
skinparam entityBackgroundColor  #BDE3FF
skinparam fileBackgroundColor  #BDE3FF
skinparam folderBackgroundColor  #BDE3FF
skinparam frameBackgroundColor  #BDE3FF
skinparam interfaceBackgroundColor  #BDE3FF
skinparam nodeBackgroundColor  #BDE3FF
skinparam queueBackgroundColor  #BDE3FF
skinparam stackBackgroundColor  #BDE3FF
skinparam rectangleBackgroundColor  #BDE3FF
skinparam storageBackgroundColor  #BDE3FF
skinparam usecaseBackgroundColor #BDE3FF

This theme is specified in Sphinx configuration file conf.py.

Example diagrams

Activity

' https://real-world-plantuml.com/umls/4886556628221952

@startuml



title Servlet Container

(*) --> "ClickServlet.handleRequest()"
--> "new Page"

if "Page.onSecurityCheck" then
  ->[true] "Page.onInit()"

  if "isForward?" then
   ->[no] "Process controls"

   if "continue processing?" then
     -->[yes] ===RENDERING===
   else
     -->[no] ===REDIRECT_CHECK===
   endif

  else
   -->[yes] ===RENDERING===
  endif

  if "is Post?" then
    -->[yes] "Page.onPost()"
    --> "Page.onRender()" as render
    --> ===REDIRECT_CHECK===
  else
    -->[no] "Page.onGet()"
    --> render
  endif

else
  -->[false] ===REDIRECT_CHECK===
endif

if "Do redirect?" then
 ->[yes] "redirect request"
 --> ==BEFORE_DESTROY===
else
 if "Do Forward?" then
  -left->[yes] "Forward request"
  --> ==BEFORE_DESTROY===
 else
  -right->[no] "Render page template"
  --> ==BEFORE_DESTROY===
 endif
endif

--> "Page.onDestroy()"
-->(*)

@enduml

Activity Diagram

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
' https://real-world-plantuml.com/umls/4886556628221952

@startuml



title Servlet Container

(*) --> "ClickServlet.handleRequest()"
--> "new Page"

if "Page.onSecurityCheck" then
  ->[true] "Page.onInit()"

  if "isForward?" then
   ->[no] "Process controls"

   if "continue processing?" then
     -->[yes] ===RENDERING===
   else
     -->[no] ===REDIRECT_CHECK===
   endif

  else
   -->[yes] ===RENDERING===
  endif

  if "is Post?" then
    -->[yes] "Page.onPost()"
    --> "Page.onRender()" as render
    --> ===REDIRECT_CHECK===
  else
    -->[no] "Page.onGet()"
    --> render
  endif

else
  -->[false] ===REDIRECT_CHECK===
endif

if "Do redirect?" then
 ->[yes] "redirect request"
 --> ==BEFORE_DESTROY===
else
 if "Do Forward?" then
  -left->[yes] "Forward request"
  --> ==BEFORE_DESTROY===
 else
  -right->[no] "Render page template"
  --> ==BEFORE_DESTROY===
 endif
endif

--> "Page.onDestroy()"
-->(*)

@enduml

Sequence

' https://real-world-plantuml.com/umls/4606798564687872


@startuml
autonumber

    participant "app: Application" as app
    participant "cm: ContentManager" as cm
    participant "item: DownloadItem" as item
    
    activate app
    activate cm
    
    note over app: User enters media info page
    
    note over app: Check if item exists
    app->cm: findItem(itemId)
    cm->cm: lookup(itemId)
    
    alt item found
        cm-->app: item
    else not found
        cm-->app: null
        app->cm: createItem(itemId, contentURL)
        cm->item: new(itemId, contentURL)
        activate item
        cm-->app: item
    
        app->cm: loadMetadata()
        note over cm
            Download and parse manifest, save in db
        end note
        cm-->app: onTracksAvailable
        cm-->app: onDownloadMetadata
        note over app: * See //track-selection// flow
    end group
    
    note over app: app is ready to start downloading
    app->item: startDownload()
    
    
    @enduml

Sequence Diagram

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
' https://real-world-plantuml.com/umls/4606798564687872


@startuml
autonumber

    participant "app: Application" as app
    participant "cm: ContentManager" as cm
    participant "item: DownloadItem" as item
    
    activate app
    activate cm
    
    note over app: User enters media info page
    
    note over app: Check if item exists
    app->cm: findItem(itemId)
    cm->cm: lookup(itemId)
    
    alt item found
        cm-->app: item
    else not found
        cm-->app: null
        app->cm: createItem(itemId, contentURL)
        cm->item: new(itemId, contentURL)
        activate item
        cm-->app: item
    
        app->cm: loadMetadata()
        note over cm
            Download and parse manifest, save in db
        end note
        cm-->app: onTracksAvailable
        cm-->app: onDownloadMetadata
        note over app: * See //track-selection// flow
    end group
    
    note over app: app is ready to start downloading
    app->item: startDownload()
    
    
    @enduml

State

' https://real-world-plantuml.com/umls/4724780511002624

@startuml

title performing I/O

[*] --> Client
Client: Process uri in Client

Client -> Server : uri-data
state Server {
  [*] -> monitor
  monitor: Server starts monitoring
  monitor: Stops at end of Server life
}

Client -> Database: Client
Database: database operations

state runcommand {
  Database -> command: Database
  command -> find: query
  command: send command to server

  monitor -> select: server-data

  find --> select
  select: select process to find proper server
  select --> find: Server

  find --> query: server
  query: encodes query and send to server
  query: decodes result
  query --> find: result

}

find -> Cursor: cursor-data
Cursor: stores docs
Cursor: retrieves new docs

Cursor -> fetch: document
fetch --> getmore
getmore: encodes query and send to server
getmore: decodes result
getmore --> fetch: new-documents


fetch -> [*]
@enduml

State Diagram

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
' https://real-world-plantuml.com/umls/4724780511002624

@startuml

title performing I/O

[*] --> Client
Client: Process uri in Client

Client -> Server : uri-data
state Server {
  [*] -> monitor
  monitor: Server starts monitoring
  monitor: Stops at end of Server life
}

Client -> Database: Client
Database: database operations

state runcommand {
  Database -> command: Database
  command -> find: query
  command: send command to server

  monitor -> select: server-data

  find --> select
  select: select process to find proper server
  select --> find: Server

  find --> query: server
  query: encodes query and send to server
  query: decodes result
  query --> find: result

}

find -> Cursor: cursor-data
Cursor: stores docs
Cursor: retrieves new docs

Cursor -> fetch: document
fetch --> getmore
getmore: encodes query and send to server
getmore: decodes result
getmore --> fetch: new-documents


fetch -> [*]
@enduml

Component

' https://real-world-plantuml.com/umls/4619683198140416

@startuml
package "ArduCopter - Simple Version" {
  [EnginesControl] -down-> Engines
  [EnginesControl] - [MainCopterProcess]
  [MainCopterProcess] - [Rangefinder]
  [Rangefinder] -down-> BottomSonicSensor
  [MainCopterProcess] -down- [GPSSignalListener]
}
package "CarDuino Nano" {
  [GPSSignalMaker] -down- [MainCarDuinoProcess]
  [MainCarDuinoProcess] -down- [CommandListener]
  [GPSSignalMaker] -up- [GPSSignalSender]
  [MainCarDuinoProcess] - [5x Rangefinders]
  [5x Rangefinders] -down-> 5xSonicSensors
  [TelemetricsSender] - [MainCarDuinoProcess]
  [TelemetricsSender] -down- MiniUSB
  [CommandListener] -left- MiniUSB
}
package "Intell 2800 - Simple Version" {
  [ComputerCommunications] -up- USB
  [ComputerCommunications] - [MainComputerProcess]
  [KinectProcessing] -down-> KINECT
  [KinectProcessing] - [MainComputerProcess]
  [VideoProcessing] -down-> Camera
  [VideoProcessing] - [MainComputerProcess] 
  [ComputerCommunications2] -up- [MainComputerProcess]
  [ComputerCommunications2] -down- WiFi
  [ComputerCommunications2] -down- Bluetooth
}
[GPSSignalListener] -down- [GPSSignalSender]
USB -up- MiniUSB
@enduml

Component Diagram

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
' https://real-world-plantuml.com/umls/4619683198140416

@startuml
package "ArduCopter - Simple Version" {
  [EnginesControl] -down-> Engines
  [EnginesControl] - [MainCopterProcess]
  [MainCopterProcess] - [Rangefinder]
  [Rangefinder] -down-> BottomSonicSensor
  [MainCopterProcess] -down- [GPSSignalListener]
}
package "CarDuino Nano" {
  [GPSSignalMaker] -down- [MainCarDuinoProcess]
  [MainCarDuinoProcess] -down- [CommandListener]
  [GPSSignalMaker] -up- [GPSSignalSender]
  [MainCarDuinoProcess] - [5x Rangefinders]
  [5x Rangefinders] -down-> 5xSonicSensors
  [TelemetricsSender] - [MainCarDuinoProcess]
  [TelemetricsSender] -down- MiniUSB
  [CommandListener] -left- MiniUSB
}
package "Intell 2800 - Simple Version" {
  [ComputerCommunications] -up- USB
  [ComputerCommunications] - [MainComputerProcess]
  [KinectProcessing] -down-> KINECT
  [KinectProcessing] - [MainComputerProcess]
  [VideoProcessing] -down-> Camera
  [VideoProcessing] - [MainComputerProcess] 
  [ComputerCommunications2] -up- [MainComputerProcess]
  [ComputerCommunications2] -down- WiFi
  [ComputerCommunications2] -down- Bluetooth
}
[GPSSignalListener] -down- [GPSSignalSender]
USB -up- MiniUSB
@enduml

Deployment

' http://plantuml.com/deployment-diagram

@startuml
actor actor
agent agent
artifact artifact
boundary boundary
card card
cloud cloud
component component
control control
database database
entity entity
file file
folder folder
frame frame
interface  interface
node node
package package
queue queue
stack stack
rectangle rectangle
storage storage
usecase usecase
@enduml

Deployment Diagram

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
' http://plantuml.com/deployment-diagram

@startuml
actor actor
agent agent
artifact artifact
boundary boundary
card card
cloud cloud
component component
control control
database database
entity entity
file file
folder folder
frame frame
interface  interface
node node
package package
queue queue
stack stack
rectangle rectangle
storage storage
usecase usecase
@enduml

Timing

' http://plantuml.com/timing-diagram

@startuml
robust "Web Browser" as WB
concise "Web User" as WU

WB is Initializing
WU is Absent

@WB
0 is idle
+200 is Processing
+100 is Waiting
WB@0 <-> @50 : {50 ms lag}

@WU
0 is Waiting
+500 is ok
@200 <-> @+150 : {150 ms}
@enduml

Timing Diagram

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
' http://plantuml.com/timing-diagram

@startuml
robust "Web Browser" as WB
concise "Web User" as WU

WB is Initializing
WU is Absent

@WB
0 is idle
+200 is Processing
+100 is Waiting
WB@0 <-> @50 : {50 ms lag}

@WU
0 is Waiting
+500 is ok
@200 <-> @+150 : {150 ms}
@enduml

Handwritten Draft Diagram

Per handwritten “To emphasize the fact that your diagrams are still under work, you can generate handwritten diagrams”.

The plantuml_handwritten.puml is included to give the handwritten effect.

1
skinparam handwritten true
docker run -u `id -u $USER`:`id -g $USER` -i --rm -v $(pwd):/home/documentation -t  docdac:ubuntu-1.0 java -jar /usr/share/plantuml/plantuml.jar -Idocs/plantuml/plantuml_cfg.puml -Idocs/plantuml/plantuml_handwritten.puml  docs/plantuml/examples/*.puml -o handwritten/

This givens a handwritten wavy effect to diagrams e.g.

Draft Sequence

' https://real-world-plantuml.com/umls/4606798564687872


@startuml
skinparam handwritten true

autonumber

    participant "app: Application" as app
    participant "cm: ContentManager" as cm
    participant "item: DownloadItem" as item
    
    activate app
    activate cm
    
    note over app: User enters media info page
    
    note over app: Check if item exists
    app->cm: findItem(itemId)
    cm->cm: lookup(itemId)
    
    alt item found
        cm-->app: item
    else not found
        cm-->app: null
        app->cm: createItem(itemId, contentURL)
        cm->item: new(itemId, contentURL)
        activate item
        cm-->app: item
    
        app->cm: loadMetadata()
        note over cm
            Download and parse manifest, save in db
        end note
        cm-->app: onTracksAvailable
        cm-->app: onDownloadMetadata
        note over app: * See //track-selection// flow
    end group
    
    note over app: app is ready to start downloading
    app->item: startDownload()
    
    
    @enduml

Sequence Diagram Draft

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
' https://real-world-plantuml.com/umls/4606798564687872


@startuml
skinparam handwritten true

autonumber

    participant "app: Application" as app
    participant "cm: ContentManager" as cm
    participant "item: DownloadItem" as item
    
    activate app
    activate cm
    
    note over app: User enters media info page
    
    note over app: Check if item exists
    app->cm: findItem(itemId)
    cm->cm: lookup(itemId)
    
    alt item found
        cm-->app: item
    else not found
        cm-->app: null
        app->cm: createItem(itemId, contentURL)
        cm->item: new(itemId, contentURL)
        activate item
        cm-->app: item
    
        app->cm: loadMetadata()
        note over cm
            Download and parse manifest, save in db
        end note
        cm-->app: onTracksAvailable
        cm-->app: onDownloadMetadata
        note over app: * See //track-selection// flow
    end group
    
    note over app: app is ready to start downloading
    app->item: startDownload()
    
    
    @enduml

Draft State

' https://real-world-plantuml.com/umls/4724780511002624

@startuml
skinparam handwritten true

title performing I/O

[*] --> Client
Client: Process uri in Client

Client -> Server : uri-data
state Server {
  [*] -> monitor
  monitor: Server starts monitoring
  monitor: Stops at end of Server life
}

Client -> Database: Client
Database: database operations

state runcommand {
  Database -> command: Database
  command -> find: query
  command: send command to server

  monitor -> select: server-data

  find --> select
  select: select process to find proper server
  select --> find: Server

  find --> query: server
  query: encodes query and send to server
  query: decodes result
  query --> find: result

}

find -> Cursor: cursor-data
Cursor: stores docs
Cursor: retrieves new docs

Cursor -> fetch: document
fetch --> getmore
getmore: encodes query and send to server
getmore: decodes result
getmore --> fetch: new-documents


fetch -> [*]
@enduml

State Diagram Draft

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
' https://real-world-plantuml.com/umls/4724780511002624

@startuml
skinparam handwritten true

title performing I/O

[*] --> Client
Client: Process uri in Client

Client -> Server : uri-data
state Server {
  [*] -> monitor
  monitor: Server starts monitoring
  monitor: Stops at end of Server life
}

Client -> Database: Client
Database: database operations

state runcommand {
  Database -> command: Database
  command -> find: query
  command: send command to server

  monitor -> select: server-data

  find --> select
  select: select process to find proper server
  select --> find: Server

  find --> query: server
  query: encodes query and send to server
  query: decodes result
  query --> find: result

}

find -> Cursor: cursor-data
Cursor: stores docs
Cursor: retrieves new docs

Cursor -> fetch: document
fetch --> getmore
getmore: encodes query and send to server
getmore: decodes result
getmore --> fetch: new-documents


fetch -> [*]
@enduml

VSCode PlantUML Extension

VSCode Plantuml Extension makes it easy to create and edit plantuml diagrams. It includes a real-time preview within VSCode.

References

  1. http://plantuml.com/ homepage

  2. http://plantuml.com/command-line

  3. real-world-plantuml.com shows many examples of PlantUML diagrams.

  4. https://www.planttext.com/ free online site where you can copyNpaste the text description to auto-generate a diagram

  5. https://www.websequencediagrams.com/ free online site where you can copyNpaste the text description to auto-generate a diagram

Todo

DFD diagram template

Attack tree templates