Drawing diagrams with PlantUML

Picture This

© Lead Image © David Castillo Dominici, 123RF.com

© Lead Image © David Castillo Dominici, 123RF.com

Author(s):

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
Figure 1: With a sequence diagram, you can show any structured transaction.

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
Figure 2: PlantUML's Gantt diagrams may not be as fancy as those done in Microsoft Project, but they are much easier to create.

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
Figure 3: A taxonomy mind map diagram that uses asterisks for indentation.
Figure 4: This mind map has the same information as shown in Figure 3, but it uses dashes and underscores for additional formatting.

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
Figure 5: PlantUML's WBS diagrams are the best choice for org charts or any other hierarchical structure.

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
Figure 6: Part of a complex flow diagram, created on the fly from PlantBuddy's GitHub site [4]. @PlantBuddy.

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.

Figure 7: With PlantUML, you can add legends, headers, footers, and more.

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
Figure 8: You can easily embed any image you want in your diagrams.

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

  1. PlantUML: http://www.plantuml.com
  2. PlantUML web server: http://www.plantuml.com/plantuml
  3. PlantUML command-line options: https://plantuml.com/command-line
  4. PlantBuddy diagram: https://github.com/anoff/plantbuddy
  5. PlantUML Reference Guide: http://plantuml.com/guide
  6. Open Iconic: https://useiconic.com/open
  7. Custom sprites: https://plantuml.com/sprite
  8. Using PlantUML: https://plantuml.com/running

The Author

Marco Fioretti (http://stop.zona-m.net) is a freelance author, trainer, and researcher based in Rome, Italy, who has been working with Free/Open Source software since 1995, and on open digital standards since 2005. Marco also is a board member of the Free Knowledge Institute (http://freeknowledge.eu).