Legacy
Upgrade from Java Spring Boot Stack 1.0 to Java Spring Boot Stack 2.0â
If a Java project was created with a version before IBM DevOps Solution Workbench 4.1.0, 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.
Security Advisory: To avoid the risk of being vulnerable to potential security threats, it is essential not to use the following when using Java Spring Boot Stack 1.0:
- Do not use any remote calls (
org.springframework.remoting.httpinvoker.*). - Do not use disallowedFields patterns in DataBinder for configuring the Kafka connection within spring.
- Do not serve static resources through the functional web frameworks WebMvc.fn or WebFlux.fn.
- Dependency Note: These issues are not directly caused by our stack but arises from its dependencies. Java Spring Boot Stack 1.0 itself is free from known vulnerabilities; however, it relies on additional dependencies that might contain security risks, particularly with no security fixes provided in the underlying version of Java 11.
- Recommended Action: Avoid using any remote calls, disallowedFields patterns or serving static files within the Java Spring Boot Stack 1.0 environment to maintain security. These security concerns are addressed in Java Spring Boot Stack 2.0, where the issue does not exist.
Java 17 Migrationâ
In order to migrate your project from Java 11 to Java 17 you should follow the Oracle JDK Migration Guide.
Spring Boot 3 Migrationâ
In order to migrate your project from Spring Boot 2 to Spring Boot 3 you should follow the Spring Boot 3.0 Migration 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.
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
General project structureâ
With Java Spring Boot Stack 2.0 the general project structure changed. The implementation files and also the generated code 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>-applicationinto your project root directory - Move all files from the folder
/src/main/filteredinto/src/main/resources - Delete the following folders
/<yourProject>-application/.framework/src/main/generated/src/main/filtered
Adjustment of solution.yamlâ
To define that the project should use Java Spring Boot Stack 2.0, a dedicated flag in the solution.yml of your project needs to be set:
- Open file
/solution.yaml - Extend the property
extensionswithjava: 17
Example:
appAcronym: "APPACRONYM"
appType: "DDD"
language: "JAVA"
# ...
extensions:
# ...
java: 17
# ...
Adjustment for DDL Script Generationâ
- Copy your settings from the plugin
jpa2ddl-maven-pluginof your pom.xml to yourapplication.yaml/application-local.yaml - For example for the delimiter:
spring.jpa:
hibernate:
hbm2ddl:
delimiter: ";"
- Remove the
jpa2ddl-maven-plugin, as its deprecated - After codegeneration use the newly created SchemaGenerator to generate ddl files
Configuring Naming Strategiesâ
After codegeneration a new configuration file for the project k5-project.yml is generated.
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â
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-codecommand to generate thepom.xmlstub 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
parentby<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-
Remove
<groupId>com.networknt</groupId><artifactId>json-schema-validator</artifactId><groupId>de.knowis.cp.sdk</groupId><artifactId>cp-framework-managed-sdk-autoconfiguration</artifactId><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><groupId>org.springframework.kafka</groupId><artifactId>spring-kafka</artifactId><groupId>io.swagger.parser.v3</groupId><artifactId>swagger-parser</artifactId><groupId>io.apicurio</groupId><artifactId>apicurio-registry-serdes-jsonschema-serde</artifactId>
-
Add
<!-- Generated Dependencies - code-generation-provider -->
<!-- This part will be overwritten -->
<dependency>
<groupId>com.networknt</groupId>
<artifactId>json-schema-validator</artifactId>
<version>1.0.77</version>
</dependency>
<dependency>
<groupId>io.apicurio</groupId>
<artifactId>apicurio-registry-serdes-jsonschema-serde</artifactId>
<version>2.4.1.Final</version>
<exclusions>
<exclusion>
<artifactId>slf4j-jboss-logmanager</artifactId>
<groupId>org.jboss.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.swagger.parser.v3</groupId>
<artifactId>swagger-parser</artifactId>
<version>2.1.16</version>
<exclusions>
<exclusion>
<groupId>io.swagger</groupId>
<artifactId>swagger-core</artifactId>
</exclusion>
<exclusion>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>kubernetes-server-mock</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-fabric8</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-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.2.0</version>
</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.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>7.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>com.github.mifmif</groupId>
<artifactId>generex</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>net.java.quickcheck</groupId>
<artifactId>quickcheck</artifactId>
<version>0.6</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Generated Dependencies - code-generation-provider -->
-
-
Adjust
resourcesand removesrc/main/filtered -
Adjust
plugins- Remove
git-commit-id-plugin - Adjust
build-helper-maven-plugin-
In
generate-sourcesreplacesrc/main/generatedbysrc/main/generated-java -
Also add
<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>
-
- Remove
-
Add
dependencyManagement<dependencyManagement>
<dependencies>
<!-- Generated Dependency Management - ode-generation-provider -->
<!-- This part will be overwritten -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2022.0.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>3.5.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-bom</artifactId>
<version>4.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Generated Dependency Management - code-generation-provider -->
</dependencies>
</dependencyManagement>
Update generated filesâ
To update the generated files, please trigger the re-generation.
This is only necessary if you have not already run k5 generate-code in the previous step
- Execute
k5 generate-codein 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.identifierwithk5.sdk.springboot.deployment.identifier - Replace
de.knowis.cp.binding.topicwithk5.sdk.springboot.binding.topic - Replace
de.knowis.cp.server.baseurlwithk5.sdk.springboot.server.baseurl - Replace
de.cp.consumer.api.bindingwithk5.sdk.springboot.api.binding - Replace
de.knowis.cp.oidc.clientRegistrationIdwithk5.sdk.springboot.oidc.clientRegistrationId - Replace
de.knowis.cp.consumer.kubernetes.namespacewithk5.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 within your implementation files.
Application.javaâ
- Open the file
/src/main/java/<yourPackage>/<yourProject>Application.java - Extend annotation
@SpringBootApplication- Add
k5.sdk.springboot.*toscanBasePackages
- Add
Example:
@SpringBootApplication(
exclude = { MongoAutoConfiguration.class, ServiceRegistryAutoConfiguration.class, OtlpAutoConfiguration.class },
scanBasePackages = {
"<yourPackage>.<yourProjectAycronym>.*" ,
"k5.sdk.springboot.*"
}
)
Custom implementationâ
The following adaptions are dependent on the features you have used during development. There might be less changes needed, than described in the following steps.
The places that need to be adapted can be identified easily by checking the compilation errors shown in your IDE
Please find the list of all possible adaptions below:
-
Replace
import <package-name>.<project-acronym>.sdk.domain.error.BusinessError;withimport k5.sdk.springboot.domain.error.BusinessError;wherever you have used it// Before
import <packagename>.<projectacronym>.sdk.domain.error.BusinessError;
// After
import k5.sdk.springboot.domain.error.BusinessError; -
Replace
import <package-name>.<project-acronym>.sdk.domain.event.DomainEvent;withk5.sdk.springboot.domain.events.model.DomainEvent;wherever you have used it// Before
import <packagename>.<projectacronym>.sdk.domain.event.DomainEvent;
// After
import k5.sdk.springboot.domain.events.model.DomainEvent; -
Replace
import de.knowis.cp.common.consumer.kubernetes.service.KubernetesServiceBindingService;withimport k5.sdk.springboot.kubernetes.service.KubernetesServiceBindingService;wherever you have used it// Before
import de.knowis.cp.common.consumer.kubernetes.service.KubernetesServiceBindingService;
// After
import k5.sdk.springboot.kubernetes.service.KubernetesServiceBindingService; -
Replace
de.knowis.cp.deployment.identifierwithk5.sdk.springboot.deployment.identifierwherever you have used it -
Replace
de.knowis.cpwithk5.sdk.springbootat all remaining places where you used classes from the generated sdk -
Replace
javaxwithjakarta// Before
import javax.annotation.PostConstruct;
// After
import jakarta.annotation.PostConstruct; -
Replace
import org.springframework.cloud.sleuth.annotation.NewSpan;withimport io.micrometer.tracing.annotation.NewSpan;// Before
import org.springframework.cloud.sleuth.annotation.NewSpan;
// After
import io.micrometer.tracing.annotation.NewSpan;
Push your changesâ
After all the changes, your project should be successfully migrated and is ready to be pushed to the remote git repository:
Use your preferred git tooling to inspect the changes before you commit them to your remote git repository
- Run
k5 compileto ensure that you do not have any compilation issues left - Run
k5 pushto 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 -solutionDesignerâ
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
After this, you have successfully upgraded your project to Java Spring Boot Stack 2.0