Drawing diagrams with PlantUML
Picture This
With PlantUML, you can quickly create all kinds of diagrams using human-readable text and reuse them anywhere.
Sooner or later, almost everybody needs to draw a diagram, whether to manage large amounts of information or organize group activities. For software developers and administrators (as well as business managers), diagrams based on the Unified Modeling Language (UML) make it easy to visualize complex systems, from software platforms to quality control departments, to see how they function.
UML stores drawings as plain text files, with a relatively intuitive syntax. If you are familiar with mind maps, you can often guess how to manually draw a diagram described by a UML file just by looking at it – even if you don't know UML! Because it is text-based, UML is extremely simple to generate with any software. You can produce hundreds of similar diagrams, with different parameters, by passing code generated on the fly by a simple shell script (or any other program) to a UML interpreter.
Additionally, UML is useful for efficiency, consistency, and version control. In a large project, UML interpreters can automatically find all the diagram descriptions in all of the project's files and generate the corresponding images in one fell swoop. The UML statements for a software algorithm or protocol's visual representation can be written as comments right above the code it visualizes in the software source file. Thanks to this integration, version control systems can store and track changes between different versions of many diagrams, just as they do with software code. The same feature makes it easy to quickly check if a diagram is consistent with the code it represents. All of this makes UML really reusable.
PlantUML [1], an open source UML diagram tool, lets you quickly create many different types of UML diagrams from text-based descriptions. In addition, you can also generate several diagram types not included in the UML standard (Gantt, mind map, WBS). While some types of PlantUML diagrams, like timing and interface mock-ups, may only be interesting to software and hardware designers, the diagram styles shown here can benefit all users.
PlantUML is perfect for beginners and intermediate users. It runs everywhere Java runs, and it is easily included in scripts. While it offers a very basic graphical interface, I prefer to write diagrams in my favorite text editor and then launch PlantUML from the command line.
Installation
The fastest way to use PlantUML is via the official web server [2], but you also can easily install it on your computer. The only prerequisite is a working java
command, which is the core part of any Java Runtime Environment (JRE). For testing some diagram types, you may also need the Graphviz utility, but that is available as a binary package for most Linux distributions. On Linux, you can check if you have a working JRE by typing the following at the prompt:
#> java -version
On Ubuntu, if JRE is not installed, you will get a notification that "the program 'java' can be found in the following packages":
* default-jre ... other Java packages...
In that case, just install the default JRE with:
#> sudo apt install default-jre
After installation (which consumed about 100MB of disk space on my computer), you can just download the Java container file, plantuml.jar
, from the website and save it in a folder of your choice.
Getting Started
To create a diagram from instructions saved into a plain text file called myumldiagram.puml
(.puml
is PlantUML's default file extension), enter the following at the prompt or in a shell script:
java -jar /path/to/plantuml.jar myumldiagram.puml
This command produces a PNG version of the diagram with the same name as the source file (in this case myumldiagram.png
) in the same folder. Other supported output formats are SVG and LaTeX. You can assign a different name and location to a diagram if desired. With the -pipe
option, PlantUML reads from standard input and "prints" the diagram on the standard output, which you can redirect wherever you want:
cat somefile.puml | java -jar plantuml.jar-pipe > /path/to/somefile.png
It is possible to process multiple UML source files with one call. If you give PlantUML a folder instead of a file, all the text files in that folder will be processed. Alternatively, you can use shell wildcards to only parse files with certain names or extensions:
java -jar /path/to/plantuml.jar "source/*/*.c"
To put all the generated images into a common folder, pass its absolute path to PlantUML with the -o
switch.
Even the simple examples shown in this article can take two to three seconds to run. If you plan to simultaneously process many UML files, take advantage of the -failfast2
and -failfast
options. -failfast2
checks if there are any errors in any of the files passed to the program and stops it without generating a diagram. -failfast
parses the code, but stops as soon as it finds one error. You must decide which option best fits your needs.
By default, PlantUML saves each diagram's full UML code inside the PNG file's metadata section, making it very easy to retrieve. The following command
java -jar /path/to/plantuml.jar -metadata statediagram.png >statediagram.puml
will save all the UML statements that generated statediagram.png
into a text file with the same base name, which allows quick changes to complex diagrams even if you did not write the code or have their UML description! A similar option, -checkmetadata
, regenerates a diagram only if the source code it contains does not match the corresponding .puml
file.
While the command-line switches mentioned here will be enough for most of your diagramming needs, you can learn about PlantUML's other command-line options in the documentation [3] or launch PlantUML with the -help
switch. You can also use the -language
switch to list all the UML keywords supported by PlantUML.
Sequence Diagrams
Sequence diagrams are frequently used in software and telecom documentation to describe exchanges between programs or communication protocols. However, as Listing 1 shows, they can describe any type of structured transaction (Figure 1). Listing 1 shows the UML source code for Figure 1.
Listing 1
Sequence Diagram
01 @startuml 02 Alice -> Bob : Hello, is the store open? 03 Bob -> Alice: Yes, it is. What do you want to buy? 04 Alice -> Bob : I want to buy some jeans 05 Alice <- Bob : Please tell me the color 06 Alice -> Bob : Black 07 Alice <- Bob : Now please tell me the size 08 Alice -> Bob : 42 09 @enduml
You can see UML's intuitiveness in Listing 1: Diagrams (with the exceptions discussed below) are enclosed between @startuml
and @enduml
statements; each line defines one element (in Figure 1, one transaction step). The direction of each step (i.e., if Alice is speaking to Bob, or vice versa) is given by the name order (line 2) or the arrow orientation (line 7). You can also draw sequencing exchanges among more than two entities.
Gantt Diagrams
You can use PlantUML instead of applications like Microsoft Project to make basic Gantt diagrams, with deadline and task dependencies. If you feed the code in Listing 2 to PlantUML, you will get a Gantt diagram like the one shown in Figure 2. While PlantUML diagrams are not as polished as Microsoft Project diagrams, the source code can be quickly written (even on your smartphone) in human-readable text. Gantt diagrams use their own beginning (line 1) and end (line 12) keywords. In addition, using scale
(line 2) makes the diagram four times bigger than PlantUML's default minimum size (note: this syntax does not work the same for all diagrams).
Listing 2
Gantt Diagram
01 @startgantt 02 scale 4 03 Project starts the 2020/03/02 04 [Prestudy] lasts 10 days and is colored in Lavender/LightBlue 05 [Milestone 1] happens at [Prestudy]'s end 06 [System simulation] lasts 9 days and is colored in Coral/Green and starts 1 day after [Prestudy]'s end 07 [Use cases def.] lasts 7 days and ends at [Prestudy]'s end 08 [Compliance\nspecs] lasts 3 days and ends at [Use cases def.]'s start 09 [Select testers] is colored in Coral/Green 10 [Select testers] lasts 5 days and starts at [Use cases def.]'s start 11 [Train testers] starts 1 days after [Milestone 1]'s end and lasts 7 days 12 @endgantt
Mind Maps
Mind maps are an excellent way to represent the relationship between concepts or objects. To draw mind maps in PlantUML, you need to enclose all the mind map's elements between the keywords @startmindmap
and @endmindmap
, starting with the main element and indenting the following elements with asterisks or dashes. Figures 3 and 4 show two mind map layouts, with their respective source code in Listings 3 and 4. Functionally speaking, Figures 3 and 4 are identical, with the only differences being orientation and boxing. In Figure 4, the root element (Carnivores) is in the center, because using dashes (lines 6 to 9, Listing 4) instead of asterisks (lines 6 to 9, Listing 3) forces the whole Canides section to the left. The underscores in lines 7 to 9 in Listing 4 tell PlantUML to not draw boxes around those elements. In mind maps, you can also use basic HTML tags for formatting, such as the underline tag (line 6 in Listings 3 and 4) and the bold face tag (lines 10 and 13 in Listings 3 and 4).
Listing 3
Mind Map Diagram
01 @startmindmap 02 * Carnivores 03 ** Felines 04 *** Felis 05 *** Panthera 06 ** <u>Canides</u> 07 *** Canis 08 **** Familiaris 09 **** Lupus 10 ** <b>Ursides</b> 11 *** Ursus 12 **** Arctos 13 **** <b>Horribilus</b> 14 @endmindmap
Listing 4
Alternative Mind Map Diagram
01 @startmindmap 02 * Carnivores 03 ** Felines 04 *** Felis 05 *** Panthera 06 -- <u>Canides</u> 07 ---_ Canis 08 ----_ Familiaris 09 ----_ Lupus 10 ** <b>Ursides</b> 11 *** Ursus 12 **** Arctos 13 **** <b>Horribilus</b> 14 @endmindmap
WBS Charts
PlantUML uses the Work Breakdown Structure (WBS) format for organizational charts. Figure 5 (source code shown in Listing 5) shows a company org chart, but you can use this type of diagram for other things, like a manufacturing process or a school syllabus.
Listing 5
WBS Diagram
01 @startwbs 02 + Board of Directors 03 ++ <u>Legal/Finance</u> 04 ++ <b>R&D</b> 05 +++ Software 06 ++++ Design 07 ++++ Testing 08 ++- Hardware 09 ++++ Digital Circuits 10 +++- PCB Boards 11 ++++ Analog Circuits 12 +++ System design 13 +++- Modeling 14 ++++ Simulation 15 ++ <b>Production</b> 16 ++- Procurement 17 +++ Manufacturing 18 ++++ Mechanics 19 ---- Electronics 20 @endwbs
The biggest challenge with WBS diagrams in UML is balancing the diagram visually (avoiding empty areas alongside crowded areas). In general, you assign hierarchy with indentation. Visual balancing is achieved by changing the section order (when possible) and by using dashes instead of plus characters to change each box's orientation (Listing 5, lines 10, 13, 16, and 19). This syntax is compatible with Emacs' Org Mode. However, WBS diagrams are still a beta feature in PlantUML, so their look and feel, if not their syntax, may change in future versions.
Flow Diagrams
Flow diagrams show the several steps that make a task or algorithm and can be used for anything from statistical analyses to cake recipes. Figure 6, which is taken from the PlantBuddy GitHub site [4], shows a PlantUML flow diagram. While the language in Figure 6's source code (Listing 6) is intuitive, you need to know how to write a while
cycle (lines 5 and 13) and how to use markers to delimit each phase of the flow. You use a colon at the beginning of a phase and semicolon at the end.
Listing 6
Flow Diagrams
01 @startuml 02 03 :read moisture level; 04 :read humidity + temperature; 05 while (sensor readings) is (invalid) 06 :wait 2s; 07 :read moisture level; 08 :read humidity + temperature; 09 :increase counter; 10 if (MAX_READING_RETRIES reached) then (yes) 11 :send controller to deep sleep; 12 endif 13 endwhile (valid) 14 :submit sensor data; 15 16 @enduml
Diagram Formatting
UML and PlantUML offer many options for controlling text formatting, as well as style and appearance.
According to the manual [5], the scale
command enlarges the generated image in several ways, including but not limited to these options:
scale 1.5 scale 200 width scale 1400*700
However, this option did not work as documented on several of my diagrams.
To format text, PlantUML supports both basic HTML tags like bold and underline, and their equivalents in Creole format, such as:
@startuml This is **bold** This is //italics// This is ""monospaced"" This is --stroked-- This is __underlined__ This is ~~waved~~
The most important formatting command in PlantUML, skinparam
(see [5] for its many attributes), lets you set fonts, background and text color, title properties, and much more. As an example, you can customize UML diagrams with skinparam
to create real templates as shown in Listing 7.
Listing 7
skinparam Customizations
01 skinparam backgroundColor transparent 02 skinparam monochrome true 03 04 skinparam titleBorderRoundCorner 15 05 skinparam titleBorderThickness 2 06 skinparam titleBackgroundColor Aqua-CadetBlue 07 08 skinparam classFontColor red 09 skinparam classFontSize 10 10 skinparam classFontName Aapex
skinparam
's only drawback is that the more you use it, the less portable your diagrams may become. This is especially true with fonts, which may not be available on all systems that will generate diagrams from your UML code.
Diagram Metadata
Besides the actual diagram, UML files can define several widgets that give context, structure, and generally make the diagrams themselves easier to understand. For brevity, Figure 7 shows all of these elements, plus it introduces a few other PlantUML features. The source code for Figure 7 is shown in Listing 8.
Listing 8
Adding Widgets
01 @startuml 02 caption Figure 1 Caption 03 title 04 <size:30><&bullhorn>Use case UML diagram<&star></size> 05 endtitle 06 07 header 08 header (not title) goes here 09 endheader 10 11 center footer You can also have a footer 12 13 legend right 14 This example shows 15 how you can add 16 <u><b>"meta-information"</b></u> 17 to any diagram 18 endlegend 19 20 left to right direction 21 skinparam packageStyle rectangle 22 actor customer 23 actor clerk 24 rectangle checkout { 25 customer -- (checkout) 26 (checkout) .> (payment) : include 27 (help) .> (checkout) : extends 28 (checkout) -- clerk 29 } 30 @enduml
In Listing 8, the actual diagram is shown in lines 20 to 29; again, you can easily understand the source code by comparing it carefully with the drawing. Lines 2 to 18 demonstrate how to define all the widgets I mentioned, from header and footer to title, legend, and captions. Line 4 requires an explanation. While the size:30
statement is self-explanatory, the &bullhorn
and &star
keywords tell PlantUML to insert the corresponding icons from the Open Iconic graphic library [6] (integrated in PlantUML) in their place.
Custom Images
In addition to the integrated icons, you can also create custom images. Listing 9 shows the source for embedding a custom image, and Figure 8 shows its output.
Listing 9
Embedding Images
01 @startuml 02 sprite tux linuxtux.png 03 Linux->World : I am here <$tux>, where are you? 04 Linux<-World : I am SO glad to see you! 05 @enduml
To do this, define a sprite
(a graphical element) with a label (tux
in my example) and associate it with an actual image on your hard drive. Next, you can place the image where you want by calling its label with the syntax shown in line 3 of Listing 8. In addition to regular images, you may define and embed custom sprites [7], which are monochrome images that are defined similarly to traditional ASCII art right inside your UML code:
startuml sprite $foo1 { FFFFFFFFFFFFFFF F0123456789ABCF F0123456789ABCF FFFFFFFFFFFFFFF }
This format is less esoteric than it may seem. Each hexadecimal digit inside the curly braces corresponds to one pixel of the image, and its value corresponds to the gray level of that pixel, with
being white, and F
being black. For further details on embedded sprites, see the PlantUML guide [5].
UML Programming
UML's creators have given it several capabilities of a real programming language.
You can include comments in your UML files to make them more readable. Single line comments start with one simple quote ('
), and multiline comments are enclosed by /'
and '/
tags.
Lines that start with exclamation marks (!
) are preprocessing directives, with which you can give PlantUML general instructions or make it interact with your system. The following
!log Now generating a Gantt Diagram
tells PlantUML to log a message, by writing it to its standard output.
PlantUML also uses variables and functions. PlantUML variables can only contain strings or integer numbers; it is good practice to give them names starting with a dollar sign ($
), like Perl. Besides storing values for later use, variables can also be used for simple flow control, to decide what to draw where:
Alice -> Bob : Are you free tonight? !if ($day == "Saturday") Alice <- Bob : yes !else Alice -> Bob : no, I'm sorry !endif
PlantUML supports three different types of functions: built-in, void, and return functions. Built-in functions, which have names starting with %
, include operators like %strlen
(string length) or %substr
(substring extraction). Other built-in functions give access to system information, like file location or the current date.
Void and return functions are recognizable, because, like variables, their names must start with a dollar sign ($
). The difference is simple between void and return functions and summarized in Listing 10.
Listing 10
Void and Return Functions
01 !function $warning($source, $recipient) 02 $source --> $recipient : Warning! You have been hacked! 03 !endfunction 04 !function $halfvalue($a) 05 !return $a/2 06 !endfunction
Void functions directly insert something (normally one statement) into the UML diagram description. In Listing 10, the $warning
function (line 1) will print a warning from user $source
to user $recipient
whenever it is called, obviously replacing $source
and $recipient
with the current values of those variables. Return functions perform a calculation or string processing and return the result (lines 4 and 5); they are often called from other functions.
In both void and return functions, you can define local variables, which are not visible from outside the function, and set default values for the arguments.
Code Management
In UML, as in software in general, reuse is almost always good, and duplication is almost always bad. You can put all the configuration and formatting functions that you regularly use in one file and make PlantUML load it as follows:
java -jar /path/to/plantuml.jar -config "./config.cfg" dir1
To do the same thing with the actual drawing code (e.g., the initial part of a sequence exchange or flow diagram) that you want to duplicate in other diagrams, you can write the corresponding code once (maybe packaging it as a function) in one file. Then !include
that file in other files every time you need it as follows:
@startuml !include common-diagrams-section.iuml .. your other UML code here @enduml
By doing this, any change in that single file will be seen and reloaded by all the files that include it the next time you run PlantUML, just as if you had copied and pasted common-diagrams-section
in each file. The !include
directive supports URLs, so you may even load code directly from the Internet or your company network. By default, a file can only be included once. You may include the same file several times in your code with the !include_many
directive, but think twice before doing it: It may make your code unmanageable.
Syntax-wise, you may also put several independent blocks of common code in the same file, each within its own @startuml
/@enduml
statements, and identify each of those blocks by their number. A directive like !include myuml.txt!1
will then load only the second (numbering starts from
) block within myuml.txt
. To improve code readability, you can assign names to a block
@startuml(id=SOME_IDENTIFIER)
and then include only that block with this statement
!include foo.txt!SOME_IDENTIFIER
Pros and Cons
With the basics covered, there are some general pros and cons to using PlantUML for creating diagrams.
PlantUML uses plain text, and very simple text at that. On one hand, this makes it extremely quick to write, without wasting time by clicking on countless options or dragging around lines and boxes.
On the other hand, this efficiency results in some loss of control. A PlantUML diagram is "inferred by a deterministic algorithm in the rendering process" [1]. Therefore, describing diagrams with text instead of just drawing them on your computer is like writing Markdown instead of using a word processor. While you can focus on your diagram's structure, the algorithms baked into PlantUML do the actual drawing. If the developers of the next PlantUML version decide to change those algorithms (or some of the graphic libraries), all your diagrams could assume a new look and feel when you upgrade, whether you like it or not.
While this may be a showstopper for some users, don't let it scare you, because there is nothing as reusable as a PlantUML diagram, and it has so many uses [8]. You can automatically create or process UML code with any major programming language. Above all, you can write, copy, and paste UML code in LibreOffice, Microsoft Office, WordPress, Etherpad, MediaWiki, and many other editors or content management systems. With the right plugins, all those programs will read that code and convert it into embedded diagrams without a hitch. What's not to like?
Infos
- PlantUML: http://www.plantuml.com
- PlantUML web server: http://www.plantuml.com/plantuml
- PlantUML command-line options: https://plantuml.com/command-line
- PlantBuddy diagram: https://github.com/anoff/plantbuddy
- PlantUML Reference Guide: http://plantuml.com/guide
- Open Iconic: https://useiconic.com/open
- Custom sprites: https://plantuml.com/sprite
- Using PlantUML: https://plantuml.com/running