Upgrade from Java Spring Boot Stack 1.0 to Java Spring Boot Stack 2.0

If a Generic Java project was created with a version before IBM Industry Solutions Workbench 4.1.1, it will be based Java Spring Boot Stack 1.0 which comes with Spring Boot 2 and Java 11. The upgrade to Java Spring Boot Stack 2.0 based on Spring Boot 3 and Java 17 is possible following this guide.

Stack Upgrade

In addition, you have to migrate the project structure and the implementation code of your service project. To do this, clone your project to your local machine and edit the files in the described order.

Tip:

It is recommended to use a separate branch for upgrading your project. This way you can ensure that the upgrade does not impact your default branch unless it is successfully done

Remove solution.yaml

Remove solution.yaml file.

General project structure

With Generic Java Stack 2.0 the general project structure changed. The implementation files is no longer meant to be under folder <yourProject>-application. To adapt your project structure, please follow the steps:

  • Move all files from the folder /<yourProject>-application into your project root directory
  • Move all files from the folder /src/main/filtered into /src/main/resources
  • Delete the following folders
    • /<yourProject>-application
    • /.framework
    • /src/main/filtered

Add k5-project.yml

Add k5-project.yml to the project root.

Example:

schemaVersion: /v1/projectConfiguration.schema.json
acronym: "APPACRONYM"
displayName: "Display name"
tags: []
stackReference:
  name: "k5-JavaSpringBoot"
  version: 2.0.0
extensions:
  apiModelling:
    enabled: false
  domainModelling:
    enabled: false
  integrationModelling:
    enabled: false
  aggregatePersistenceSupport:
    databaseType: "Mongo"
    enabled: false
  businessEventSupport:
    enabled: false
    version: '2.0'
  sagaPatternSupport:
    enabled: false
  swaggerUISupport:
    enabled: false
  unitTestingSupport:
    enabled: false
additionalConfig:
  basePackage: "example.package.name"
creationTs: '1655991139241'
creator: creator name
creatorId: 7234cb62-1b4e-470c-b059-975b87684663

Configuring Naming Strategies

With Java Stack 2.0 a new naming strategy default was introduced. Table and column names for jpa annotations have to be specified in the designer. No default names are generated anymore. To keep the old way use the naming strategy legacy (for further information on overwriting defaults, see JPA Configuration and MongoDB Configuration).

  aggregatePersistenceSupport:
    databaseType: DB2
    enabled: true
    namingStrategies: default

Adjustment of pom.xml

Projects using Java Spring Boot Stack 2.0 also require some changes in the pom.xml of your project. You can either let the pom.xml re-generate automatically or do a manual migration. The automatic re-generation of the pom.xml is the recommended approach if you have not made any custom changes in your pom.xml.

Option 1: Re-generate pom.xml

Note:

If you re-generate your pom.xml, the dependencies you have added manually and other changes you made to the pom.xml will get lost. Please make sure that you remember all custom changes before deleting the file.

  • Delete the file /pom.xml
  • Trigger k5 generate-code command to generate the pom.xml stub automatically
  • Apply all your custom changes to the generated stub file
  • Ensure your version number is set correctly
  • Depending on your IDE, it might be necessary to trigger a refresh of your project so that it recognizes the new generated files properly
    • e.g. in Eclipse 'Maven' --> 'Update Project'

Option 2: Manual migration of pom.xml

  • Remove repositories

  • Replace parent by

      <parent>
        <!-- Generated Parent - code-generation-provider -->
        <!-- This part will be overwritten -->
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>3.1.2</version>
        <relativePath/>
        <!-- Generated Parent - code-generation-provider -->
      </parent>
  • Replace <java.version>11</java.version> by <java.version>17</java.version>

  • Adjust dependencies

    • Replace
    <dependencies>
      <dependency>
        <groupId>de.knowis.cp.sdk</groupId>
        <artifactId>cp-framework-sdk-autoconfiguration</artifactId>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
      </dependency>
      <!-- if we do not want to use kafka at all, we simply can omit the following dependency -->
      <dependency>
        <groupId>org.springframework.kafka</groupId>
        <artifactId>spring-kafka</artifactId>
      </dependency>
    
      <!-- add this dependency if you want to run the api locally within swagger ui
      <dependency>
        <groupId>org.springdoc</groupId>
        <artifactId>springdoc-openapi-ui</artifactId>
      </dependency>
      -->
    </dependencies>
    • With
    <dependencies>
      <!-- Generated Dependencies -->
      <!-- This part will be overwritten -->
      <dependency>
        <groupId>io.fabric8</groupId>
        <artifactId>kubernetes-server-mock</artifactId>
        <scope>test</scope>
      </dependency>
      <dependency>
        <groupId>io.micrometer</groupId>
        <artifactId>micrometer-tracing</artifactId>
      </dependency>
      <dependency>
        <groupId>io.micrometer</groupId>
        <artifactId>micrometer-tracing-bridge-otel</artifactId>
      </dependency>
      <dependency>
        <groupId>io.opentelemetry.instrumentation</groupId>
        <artifactId>opentelemetry-instrumentation-api</artifactId>
        <version>1.32.1</version>
      </dependency>
      <dependency>
        <groupId>io.opentelemetry.instrumentation</groupId>
        <artifactId>opentelemetry-instrumentation-api-semconv</artifactId>
        <version>1.32.0-alpha</version>
      </dependency>
      <dependency>
        <groupId>io.opentelemetry.instrumentation</groupId>
        <artifactId>opentelemetry-spring-boot-starter</artifactId>
        <version>1.32.0-alpha</version>
      </dependency>
      <dependency>
        <groupId>net.logstash.logback</groupId>
        <artifactId>logstash-logback-encoder</artifactId>
        <version>7.4</version>
      </dependency>
      <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-collections4</artifactId>
      </dependency>
      <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
      </dependency>
      <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
      </dependency>
      <dependency>
        <groupId>org.springdoc</groupId>
        <artifactId>springdoc-openapi-starter-common</artifactId>
        <version>2.3.0</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-client</artifactId>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-kubernetes-fabric8</artifactId>
      </dependency>
      <!-- Generated Dependencies -->
    </dependencies>
  • Adjust resources and remove src/main/filtered

  • Adjust plugins

  • Replace

    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
      </plugin>
      <plugin>
        <groupId>pl.project13.maven</groupId>
        <artifactId>git-commit-id-plugin</artifactId>
        <executions>
          <execution>
            <goals>
              <goal>revision</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
    • With
        <plugins>
          <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>build-helper-maven-plugin</artifactId>
            <executions>
              <execution>
                <id>add-source</id>
                <phase>generate-sources</phase>
                <goals>
                  <goal>add-source</goal>
                </goals>
                <configuration>
                  <sources>
                    <source>src/main/generated-java</source>
                  </sources>
                </configuration>
              </execution>
              <execution>
                <id>add-test-source</id>
                <phase>generate-sources</phase>
                <goals>
                  <goal>add-test-source</goal>
                </goals>
                <configuration>
                  <sources>
                    <source>src/test/generated-java</source>
                  </sources>
                </configuration>
              </execution>
            </executions>
          </plugin>
          <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
          </plugin>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
          </plugin>
        </plugins>
  • Add dependencyManagement

    <dependencyManagement>
      <dependencies>
        <!-- Generated Dependency Management -->
        <!-- This part will be overwritten -->
        <dependency>
          <groupId>com.google.guava</groupId>
          <artifactId>guava</artifactId>
          <version>33.0.0-jre</version>
        </dependency>
        <dependency>
          <groupId>com.squareup.okio</groupId>
          <artifactId>okio-jvm</artifactId>
          <version>3.8.0</version>
        </dependency>
        <dependency>
          <groupId>org.apache.tomcat.embed</groupId>
          <artifactId>tomcat-embed-core</artifactId>
          <version>10.1.18</version>
        </dependency>
        <dependency>
          <groupId>org.apache.tomcat.embed</groupId>
          <artifactId>tomcat-embed-el</artifactId>
          <version>10.1.18</version>
        </dependency>
        <dependency>
          <groupId>org.apache.tomcat.embed</groupId>
          <artifactId>tomcat-embed-websocket</artifactId>
          <version>10.1.18</version>
        </dependency>
        <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-dependencies</artifactId>
          <version>2022.0.5</version>
          <type>pom</type>
          <scope>import</scope>
        </dependency>
        <dependency>
          <groupId>org.xerial.snappy</groupId>
          <artifactId>snappy-java</artifactId>
          <version>1.1.10.5</version>
        </dependency>
        <dependency>
          <groupId>org.yaml</groupId>
          <artifactId>snakeyaml</artifactId>
          <version>2.2</version>
        </dependency>
        <!-- Generated Dependency Management -->
      </dependencies>
    </dependencyManagement>

Update generated files

To update the generated files, please trigger the re-generation.

Note:

This is only necessary if you have not already run k5 generate-code in the previous step

  • Execute k5 generate-code in the command line inside your project directory

Adjustment of application.yaml

Open file /src/main/resources/application.yaml

  • remove property de.knowis.cp.ds

Adjustment of application-local.yaml

For local development, some keys in the files /src/main/resources/application-local.yaml and /src/main/resources/application-local.template.yaml need to be overwritten:

  • Replace de.knowis.cp.deployment.identifier with k5.sdk.springboot.deployment.identifier
  • Replace de.knowis.cp.binding.topic with k5.sdk.springboot.binding.topic
  • Replace de.knowis.cp.server.baseurl with k5.sdk.springboot.server.baseurl
  • Replace de.cp.consumer.api.binding with k5.sdk.springboot.api.binding
  • Replace de.knowis.cp.oidc.clientRegistrationId with k5.sdk.springboot.oidc.clientRegistrationId
  • Replace de.knowis.cp.consumer.kubernetes.namespace with k5.sdk.springboot.kubernetes.namespace

Adjustment of Java implementation code

To get your custom implementation working for the new stack, some manual changes need to be done according to your implementation. The following folders and sub files can be removed if you are not using them.

  • java/config/
  • java/provider/
  • java/service/

Application.java

  • Open the file /src/main/java/<yourPackage>/<yourProject>Application.java
  • Extend annotation @SpringBootApplication
    • Add k5.sdk.springboot.* to scanBasePackages Example:
@SpringBootApplication(
  exclude = { MongoAutoConfiguration.class, ServiceRegistryAutoConfiguration.class, OtlpAutoConfiguration.class },
  scanBasePackages = {
    "<yourPackage>.<yourProjectAycronym>.*" ,
    "k5.sdk.springboot.*"
  }
)
  • Replace the following import
// remove 
"import javax.annotation.PostConstruct;"
// add
"import jakarta.annotation.PostConstruct;"
Note:

you can always enable/disable any supported extension according to your needs.

Push your changes

After all the changes, your project should be successfully migrated and is ready to be pushed to the remote git repository:

Tip:

Use your preferred git tooling to inspect the changes before you commit them to your remote git repository

  • Run k5 compile to ensure that you do not have any compilation issues left
  • Run k5 push to push your changes to the remote git
  • Trigger a deploy or release pipeline and verify that everything is running smoothly
  • If you have used a separate branch for upgrading (as recommended), merge your branch into your default branch after you have ensured that everything still works

Update project in Solution Designer

Updating your project in Solution Designer is important to get the possibility to make use of additional features in the new stack also during the design of your project. This will not happen automatically and requires some manual steps in the Solution Designer.

  • Open your project in Solution Designer
  • Open your default branch
  • Trigger the action "Reset to remote" to pull the changes from your remote branch
Note:

After this, you have successfully upgraded your project to Java Spring Boot Stack 2.0