: code generator tutorial

Lesson 4: Enable or Disable Types

In the previous lesson we saw that the code generator first expands the set of types types that you asked for to its transitive closure, but then it "prunes" that large set down by using its rules for type enablement.

It does an excellent job at getting you close to where you need to be, but no automated tool can claim to understand your intent perfectly, so there are going to be some Java types that are enabled when in fact you would prefer them disabled. There are also going to be some Java types that you would really like to use from C++ but the code generator did not enable them.

Another issue may be related to the handling of Java exceptions in C++. Maybe you would prefer to disable all concrete Exception types and only generate a proxy for the Throwable type. In your C++ code you would then just catch Throwable and handle it generically as a "Java-related problem."

The code generator allows you to override its default choices for type enablement on a type-by-type basis. You will learn how to do that in this lesson.

This lesson builds on the JDBC use case we just introduced in the previous lesson. If you still have the model open you can jump straight in, otherwise please recreate the model following the steps in the previous lesson, or if you know your way around already, create a new model, set its name to JDBC and import java.sql.*,javax.sql.*. This will get you to where you need to be.

Step By Step Instructions

  1. Expand the java.lang Package

    You should now see something looking similar to the image below: The GUI after import

    As explained in the previous lesson, several types in this package have been enabled by the code generator because they are referenced by the public APIs of the JDBC API types that you imported into the model. Depending on the version of the JRE that you are importing from, the exact set of types that is enabled might differ.

    When we retested the tutorial recently with a Java 8 JRE, the Integer type was enabled, but in the screenshot, which is based on an earlier Java version, it is disabled. This shows two things: 1) you really want to control the JRE that you import from, and 2) you really need to be able to manually adjust the type enablement after an import.

    As mentioned, the Integer type might be enabled or not, but the Long type was disabled in both cases. Why worry about Integer and Long? Because having used JDBC in Java, we know that the concrete java.lang.Number types are very useful! Having used JDBC before, we know that we need to generate proxy types for all the primitive wrapper types and also for a bunch of collection types from the java.util package.

  2. Import Some Missing Types

    First off, we notice that the java.lang.Short wrapper type is not even part of the model, so there is no way we can enable it. Obviously it was not referenced explicitly by the imported APIs. Let's correct that by importing it. You know how to import types from the classpath, so do that for java.lang.Short.

    It shows up in the model, displayed in black boldface to indicate that you specifically asked for this type. You also notice that java.lang.Number is now enabled (because it is the public super type of an explicitly imported type).

    We always recommend that you finish all imports before you start to manually adjust type enablement. Import operations can have an effect on the enablement of referenced types and should therefore be finished before we make final adjustments.

  3. Enable Types

    Click on the Long type in the Navigation pane. It should be displayed in selected state now.

    Click on the Enable icon icon from the toolbar or choose Enable Elements from the Edit menu. When you deselect the type by clicking elsewhere you should now see it displayed in blue boldface. This is the visual representation of a type that you manually enabled.

    You can repeat this for any types that you wish to enable. you can also multiselect several types and then apply the Enable command to all of them at once.

  4. Check the Model State

    When we look at the Model State pane we see the commands that our type enablements are translated to. You should see something like this:

    ^javamodel('javamodel.12796493465.2').enabletypes(
        ^javatypeselector({include:'java.lang.Long'}),
        true
    );

    The ^javatypeselector() expression probably gives you a hint that this command can be used for more than just enabling or disabling one type. Indeed, Java type selectors can support many criteria that all together specify a typeset to which a command will be applied.

  5. Disable Types

    Click on the java.util.concurrent package in the Navigation pane. It should be displayed in selected state now.

    Click on the Disable icon icon from the toolbar or choose Disable Elements from the Edit menu. A dialog will pop up that asks you whether you want to disable packages recursively or just the selected package. Click "No" to decline recursive mode.

    You should see all types in the package displayed in red and normal weight. This is the visual indicator for Java types that have been manually disabled. None of these types, even if they were previously enabled, will have a corresponding proxy type generated.

    When we look at the Model State pane again we should see something like this:

     ^javamodel('javamodel.12796493465.2').enabletypes(
         ^javatypeselector({include:'java.util.concurrent.*'}),
         false
     );

    Had you selected to disable packages recursively, the include pattern would use the ** pattern instead of the * pattern.

Take-Away Points

  1. You can override the enabled status of every element in the model.

    While the code generator provides reasonable (and configurable) defaults for enablement, you are not tied to those defaults.

  2. Java types only result in proxy types if they are enabled.
  3. Feel free to disable a lot of types.

    Just because your Java application relies on 20,000 types at runtime does not mean that you have to generate 20,000 proxy types! The only types you really need to generate are the ones that you are explicitly using in your proxy application.

    Use package level disablement whenever possible because that will continue doing the right thing even if you add new types to that package in the future.

  4. Check for and enable forgotten support types.

    The code generator does not know which types you intend to use in your proxy application. You almost always need the Object and String types, as well as some types from the java.util package. Rarely can you get away with generating only types from your specific problem domain.