Diving Deeper into PlantUML: Customization Options

In a previous spin post, Sivhaun went over the basics of using PlantUML to create a database schema. That’s a really cool starting point, but it just scratches the surface of what Plant is capable of. There are a whole host of customization options that can really tailor your diagram to your specific use case. This can result in a huge improvement to the usability of writing or modifying your diagram while also making it much more readable graphically as well. Let’s dig into how to customize PlantUML.

Starting Setup

Let’s start with a simple example, using a simple database schema as an example:

@startuml

object account {
    id: long not null
    email: string not null
}

object user {
    id: long not null
    account_id: long not null
    name: string
}

object session {
    id: long not null
    user_id: long not null
    opened: timestamp not null
    closed: timestamp
}

account ||--|{ user
user ||--|{ session

@enduml

Functions

This is great and all, but what if we want this to look more like a classic schema diagram? We can define our own custom entity that uses an easily recognizable symbol for a database table.

@startuml

!define table(x) entity x << (T, white) >>

table(account) {
    id: long not null
    email: string not null
}

table(user) {
    id: long not null
    account_id: long not null
    name: string
}

table(session) {
    id: long not null
    user_id: long not null
    opened: timestamp not null
    closed: timestamp
}

account ||--|{ user
user ||--|{ session

@enduml

customize PlantUML
Okay, that’s pretty cool! We defined our own function that returns the standard entity header that we recognize as a database table. That’s a pretty small improvement, though. We should really make some bigger changes. It would be really nice to denote primary and foreign keys with standard recognizable symbols to really make this diagram easy to parse at a glance.

@startuml

!define table(x) entity x << (T, white) >>
!define primary_key(x) **<color:#b8861b><&key> x**
!define foreign_key(x) <color:#aaaaaa><&key> x
!define unique(x) x*
!define column(x) x

table(account) {
    primary_key(id): long not null
    unique(email): string not null
}

table(user) {
    primary_key(id): long not null
    foreign_key(account_id): long not null
    column(name): string
}

table(session) {
    primary_key(id): long not null
    foreign_key(user_id): long not null
    column(opened): timestamp not null
    column(closed): timestamp
}

account ||--|{ user
user ||--|{ session

@enduml

Entity member pointers

Ok, now we’re REALLY getting somewhere. We turned all our columns into functions that can return the pre-formatted text that gives us easily identifiable schema items. Color-coded key icons identify table keys with bold signifying primary, and an asterisk denotes a unique column. One thing that still bugs me, though, is that table connections just point from one object to another. In a schema, however, actual columns point to other columns, as a foreign key has to reference an actual column in another table. Let’s see what we can do about that.

account::id ||--|{ user::account_id
user::id ||--|{ session::user_id

customize PlantUML
Well that’s pretty nice, but the curved lines look a little goofy. It would be nice to re-organize this so they were easier to see at a glance.

@startuml

left to right direction
!define table(x) entity x << (T, white) >>
!define primary_key(x) **<color:#b8861b><&key> x**
!define foreign_key(x) <color:#aaaaaa><&key> x
!define unique(x) x*
!define column(x) x

...

customize PlantUML

More Ways to Customize PlantUML

Now that’s what I call a schema diagram. It’s now pretty easy to write and add to tables, and it’s certainly easier to read these tables at a glance. The truth is that’s STILL only scratching the surface of what PlantUML can do. Not only are there LOTS more diagram types, there’s so much more you can do if you really want to dive deep into the language features of Plant. Creating variables so you don’t have to type “long not null” a million times is as easy as defining a variable !$id = "long not null" and referencing it with $id. You can write conditional statements, loops, add emoticons, and so much more. The next time you reach for a visual editor for diagramming, consider if you can really swap to code as visuals and never have to move and reconnect lines and graphics again!