Burleigh Bear
Burleigh Bear

Reputation: 3314

Generating multiple java Enums from a single table, using JOOQ

I have a table in my database schema which contains configuration information for an application that I'm building. I'd like to generate a number of enums based on the contents of the table. I'm currently using JOOQ in my build scripts to generate other, standard JOOQ classes from the same database, and am hoping that I can obtain this new functionality through JOOQ.

For example, if the table contained the following data

Product        Component    PresentationOrder
HydroProduct   Boat         1
HydroProduct   Canoe        2
HyrdoProduct   Ship         3
LandProduct    Car          1
LandProduct    Bike         2

Then I'd want to generate two enums

hydroProduct.Components { Boat, Canoe, Ship; }

and

landProduct.Components {Car, Bike; }

where hydroProduct and landProduct are packages, and the enums are both called Components.

The precise details are up for grabs (e.g. I'd be fine with different naming conventions, so any suggestions are welcome), but the principal (two enums from the one table, based on the data therein) is, at least for this question, the thing that I need.

Having read the JOOQ docs, I see that generating Enums was once a part of JOOQ, and then removed. I can't see the "obvious" way of doing what I want in JOOQ, but it's a pretty amazing library, so I'm guessing that there might be one.

EDIT

A number of commenters have questioned the overall approach, which I understand. I'd like to avoid that kind of conversation - it's basically impossible for me to debate that level of design over this forum. This approach (code generation based on DDL and SQL) is very well tested within my organisation, and has had a very large amount of design scrutiny.

Just for the record, here's an outline the pipeline. I'm putting it in because I appreciate that people have spent time considering my original question, and I'd like to make it clear how the question fits into our overall dev system.

Project One holds some bootstrapping classes, some DDL and some SQL scripts that contain the data constants that our overall system uses. It's output includes (amongst other stuff), some .jar files containing compiled versions of classes generated. These basically comprise the core agreed vocabulary that the rest of our system uses to communicate.

Project Two holds java source code, which makes use of the various artefacts generated from project one. Before project two ever gets compiled, artefacts from project one can be assumed to have been generated. So, for example, an Enum generated from data held in project one can be used, at compile time, in project two.

Our build scripts build project one, and make the outputs available for project two. This includes generating Eclipse project files so that users of project two can check-out, build, and open eclipse for any branch of the project and it "just works".

There are other projects (including in different languages, e.g. Javascript) that also make use of the artefacts generated by project one.

The key benefit of this approach is that, when the data in project one changes, and the definitions of classes and enums in project one therefore change, project two reflects this change with compile-time errors, rather than run-time errors. The benefits of this in practice are absolutely enormous. There is a setup-cost, yes, but in our experience tools like JOOQ (which we use to generate the outputs of Project 1) have made us incredibly more productive than we used to be.

This is especially the case where we ship desktop, in-browser, and J2EE components and they all need to talk together.

Upvotes: 2

Views: 978

Answers (1)

Lukas Eder
Lukas Eder

Reputation: 220842

This won't be an exhaustive answer, as the question is a bit opinionated, but I can provide some authoritative background on the history of this feature in jOOQ:

Having read the JOOQ docs, I see that generating Enums was once a part of JOOQ, and then removed.

Yes, the reason for removal was precisely because the then-existing implementation was far from sophisticated enough to accommodate, for instance, your particular use-case.

Code generation is a very ad-hoc "science" and it is extremely difficult to maintain a configuration API backwards compatibly, which can accommodate all the possible use-cases... For instance, the fact that you want to map parts of your master data onto packages, class names being constant, ordering custom is rather particular, not generic.

Furthermore, where should generated enums be referenced from? The original implementation replaced foreign keys (e.g. Integers) by enum references in the generated code. This might not at all be what you want in some cases, where you do want to join the master data in its raw form, not as a generated enum.

Long story short, this was an eagerly added feature in jOOQ 1.x, which was extremely hard to maintain during major internal refactorings that were needed to create jOOQ 3.x, which is why it was dropped.

I can't see the "obvious" way of doing what I want in JOOQ, but it's a pretty amazing library, so I'm guessing that there might be one.

Not out of the box. I'd recommend using a templating language like Velocity or Xtend and generate the code manually as part of your build. You could, in fact, even generate custom Converter or Binding implementations to bind your enums to the relevant referencing columns.

Upvotes: 1

Related Questions