Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-10055

STC does not support self bounded types

    XMLWordPrintableJSON

    Details

      Description

      Some popular libraries use self bounded types for creating builder hierarchies. For example,
      PostgreSQLContainer (from Tescontainers library) is declared as

      public class PostgreSQLContainer<SELF extends PostgreSQLContainer<SELF>> extends JdbcDatabaseContainer<SELF>
      

      where JdbcDatabaseContainer is declared as

      public abstract class JdbcDatabaseContainer<SELF extends JdbcDatabaseContainer<SELF>> extends GenericContainer<SELF> implements LinkableContainer
      

      and so on.

      In the following example (tested with Groovy Console), I'm trying to create and modify such an object with its corresponding fluent API:

      import org.testcontainers.containers.PostgreSQLContainer
      import groovy.transform.CompileStatic
      
      @Grab("org.testcontainers:testcontainers:1.15.3")
      @Grab("org.testcontainers:postgresql:1.15.3")
      @CompileStatic
      class TestcontainersTester {
        static void testSome() {
          PostgreSQLContainer postgresqlServer = new PostgreSQLContainer()
              .withExposedPorts(5432)
              .withEnv(["TZ": "Europe/Paris"])
              .withDatabaseName("my_database")
              .withUsername("user")
              .withPassword("pass")
      
      // Working alternative 1
      //    PostgreSQLContainer postgresqlServer = new PostgreSQLContainer<PostgreSQLContainer<PostgreSQLContainer<PostgreSQLContainer<PostgreSQLContainer>>>>()
      //        .withExposedPorts(5432)
      //        .withEnv(["TZ": "Europe/Paris"])
      //        .withDatabaseName("my_database")
      //        .withUsername("user")
      //        .withPassword("pass")
      
      // Working alternative 2
      //    PostgreSQLContainer postgresqlServer = new PostgreSQLContainer<>()
      //    postgresqlServer.withExposedPorts(5432)
      //    postgresqlServer.withEnv(["TZ": "Europe/Paris"])
      //    postgresqlServer.withDatabaseName("my_database")
      //    postgresqlServer.withUsername("user")
      //    postgresqlServer.withPassword("pass")
      
          println postgresqlServer
        }
      }
      
      TestcontainersTester.testSome();
      

      Unfortunately, STC complains with several errors:

      4 compilation errors:
      
      [Static type checking] - Cannot call SELF#withEnv(java.util.Map <java.lang.String, java.lang.String>) with arguments [java.util.LinkedHashMap <java.lang.String, java.lang.String>] 
       at line: 11, column: 17
      
      [Static type checking] - Cannot find matching method java.lang.Object#withDatabaseName(java.lang.String). Please check if the declared type is correct and if the method exists.
       at line: 12, column: 26
      
      [Static type checking] - Cannot find matching method java.lang.Object#withUsername(java.lang.String). Please check if the declared type is correct and if the method exists.
       at line: 13, column: 22
      
      [Static type checking] - Cannot find matching method java.lang.Object#withPassword(java.lang.String). Please check if the declared type is correct and if the method exists.
       at line: 9, column: 44
      

      There are two working alternatives in the example. "Alternative 1" is not really practical, but maybe it can help with solving the issue. "Alternative 2" is an actual practical workaround that can be further improved by using the "with" method.

      Tnx

        Attachments

          Activity

            People

            • Assignee:
              emilles Eric Milles
              Reporter:
              dmurat Damir Murat
            • Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated: