Skip to main content

Debug Applications

Remote Debugging

Overview

This guide outlines the steps required to set up and perform remote debugging for a Java-based service in your environment. It presents two methods to enable debugging: adding the Java service as a component in application composition or configuring a single deployment via the Configuration Management API. The setup will allow you to debug your Java application in real-time using your preferred Integrated Development Environment(IDE), with the ability to forward ports and attach to a remote runtime.

Prerequisites

Before proceeding, ensure you have the following:

  • A port-forwarding tool, such as kubectl or oc CLI.
  • An IDE (e.g., IntelliJ IDEA) configured for Java development.

Steps for Remote Debugging Setup

1. Configure the Service for Remote Debugging

Application Composition:

Once your Java service is added as a component in the application composition, follow these steps to configure the project for remote debugging:

  1. Open the configuration for the component.

  2. Apply the following custom configuration options:

    • Autoscaling: Set enabled:false (This ensures that only one pod is active for debugging purposes).
    • Replica Count: Set replicaCount:1 (This ensures that only one instance of the application is running).
    • Remote Debugging: Set enabled: true
  3. Save the configuration and commit the changes.

Single Deployment:

You can configure remote debugging by directly using the Configuration Management API for a single deployment. You could update solution configurations using a curl command like the one below:

curl -X 'POST' \
'https://{your-hostname}/api/cfg/v1/runtimes/{runtimeName}/solutions/{solutionAcronym}/configurations/{configurationName}' \
-H 'accept: */*' \
-H 'Authorization: Bearer {BearerToken}'\
-H 'Content-Type: text/plain' \
-d 'remoteDebugging:
enabled: true
autoscaling:
enabled: false
replicaCount: 1'
ParameterTypeDescription
configurationNamestringThe name of the configuration: ssob-sdo-values-yaml
runtimeNamestringThe name of the specific k5-project, e.g. dev-stage
solutionAcronymstringThe acronym of a solution, e.g. ORDERS

This method allows you to apply remote debugging settings without needing to adjust the application composition.

warning

You will need to re-deploy your service after this configuration.

2. Clone the Project Locally

Once the application is configured and the changes are committed, you can proceed with cloning the project to your local environment:

  • Clone the project
  • Ensure that all necessary dependencies are installed and the project builds successfully.

3. Setup Your IDE for Remote Debugging

To configure your IDE to connect to the remote application for debugging, follow these steps:

  1. Open your Java project in your IDE.

  2. Create a new Remote Debug Configuration.

  3. Set the following options in the configuration:

    • Host: localhost
    • Port: 5005
    • Command-line arguments: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005

This configuration will allow your IDE to connect to the remote application's JVM running on the pod.

4. Port Forwarding

To enable remote debugging, you will need to forward the port from the remote pod to your local machine. Use the following command to set up port forwarding:

kubectl port-forward PODNAME 5005:5005 -n NAMESPACE

Replace PODNAME with the name of your pod and NAMESPACE with the appropriate namespace for your application. This will allow traffic on port 5005 (used by the debugger) to be forwarded to your local machine.

5. Start Debugging

Once the port forwarding is active and your IDE is configured, you can begin debugging:

  1. In your IDE, set breakpoints at desired locations in your code.

  2. Start the remote debugger using the configuration you created.

  3. Use the Swagger UI of the deployed solution from the solution envoy to trigger requests to your application, and the debugger will stop at the breakpoints for inspection.

Optional Configuration Settings

You can further customize the debugging behavior by modifying the following optional settings:

  • Session Timeouts: The default timeoutSeconds for remote debugging is set to 600 seconds (10 minutes). You can adjust this value based on your session requirements.

  • Additional Environment Variables: If your debugging scenario requires additional Java runtime options, you can modify the JAVA_TOOL_OPTIONS environment variable.

remoteDebugging:
enabled: true
timeoutSeconds: 600
portName: debug-port
containerPort: 5005
protocol: TCP
javaToolOptions: "-Xdebug -agentlib:jdwp=transport=dt_socket,address=0.0.0.0:5005,server=y,suspend=n"

Conclusion

By following these steps, you can easily set up remote debugging for your Java application, allowing you to inspect the runtime behavior of your code in real-time. This setup helps accelerate debugging workflows without requiring local container environments.

Debugging via test-cases

Run locally with profiles

Prerequisites

At this point it is assumed, that the initial setup and the mandatory commands of the Solution CLI have been performed and executed as described here.

Now its always helpful if you can run, test and debug your service project locally. To achieve that we need to provide some needed configuration.

Configuration approaches

  • Have a valid deployed project and use its k8s configuration maps to load bindings for your database and Kafka.
  • Provide configuration values to connect to your local database and Kafka broker.
warning

If you choose to use deployed project k8s configuration maps, you need to log in to your OpenShift cluster via oc CLI and run proper oc proxy command to be able to connect to your OpenShift namespace Database and Kafka clusters.

Setting up local profile

💡tip

Use /src/main/resources/application-local.template.yaml as the basis to create an application-local.yaml file and override properties needed for the local profile.

First add your service project acronym:

solution:
acronym : "project acronym"

Dependent on the features relevant for your project, please see below sections for further configurations (database, kafka, Swagger UI settings).

OpenShift k5-project namespace bindings

ℹ️note

How to use bindings from the OpenShift k5-project is depending on whether your project is based on Java Spring Boot Stack 1.0 or Java Spring Boot Stack 2.0

Java Spring Boot Stack 2.0

To load bindings from the OpenShift k5-project namespace use the following configuration:

k5.sdk.springboot.kubernetes.namespace: <k5-Project>
Java Spring Boot Stack 1.0 (Deprecated)

To load bindings from the OpenShift k5-project namespace use the following configuration:

de:
knowis:
cp:
consumer:
kubernetes:
namespace: <k5-Project>

Auto configuration features

Adjust the following configuration for toggling deployment features: (only affecting project during local runtime, not to be confused with Extensions)

# To enable / disable some auto configuration features
feature:
# toggle security for rest apis - if turned off, api calls are no longer secured
security:
enabled: true
# toggle openapi - if turned off, openapi specification is no longer used
openapi:
enabled: true
# toggle narayana security - if turned off, saga transactions are no longer secured
secure-narayana:
enabled: true

Database configuration

Depending on your service project selected Persistence Type [MongoDB] or [RDBMS], you can configure your database as below.

MongoDB persistence

Load MongoDB configuration from k8s configuration map

spring:
data:
mongodb:
secretName: # read from kubernetes secret

To access a local MongoDB, you can set the spring.data.mongodb.uri property to change the URL and configure additional settings, as shown in the following example:

spring:
data:
mongodb:
uri: mongodb://<username>:<secret>@<host>:<port>/<database>
database: <database>

Alternatively, you can specify connection details using discrete properties. For example, you might declare the following settings as shown below:

spring:
data:
mongodb:
host: <host>
port: <port>
database: <database>
username: <username>
password: <password>
RDBMS Persistence

To access your service project RDBMS database, you need to add below configuration

spring:
datasource:
url: "jdbc:<subprotocol name>://<host>:<port>/<database-name>"
username: <user name>
password: <password>
driver-class-name: <Your database driver class>

Kafka configurations

Load event topic binding configuration from k8s secret(s)

  1. You need to add your k5-project as described in Here

  2. You need to have proper oc proxy and oc port forwarding to be able to access your OpenShift k5 project event topic binding secret(s) and their configured Kafka cluster.

Alternatively, you can configure to use your Kafka broker and your own local topic binding secret(s).

  1. Install and configure your Kafka broker see kafka

  2. For each topic add proper event topic binding configuration like below

Java Spring Boot Stack 2.0
k5.sdk.springboot.binding.topic:
topicBindings:
<Topic-Alias-1>:
topicName: "<Kafka topic name>"
kafkaBinding: "<Kafka-Secret-1>"
<Topic-Alias-2>:
topicName: "<Kafka topic name>"
kafkaBinding: "<Kafka-Secret-2>"
kafkaBindings:
<Kafka-Secret-1>:
kafka_brokers_sasl: ""
password: ""
user: ""
<Kafka-Secret-2>:
kafka_brokers_sasl: ""
password: ""
user: ""
Java Spring Boot Stack 1.0 (Deprecated)
de.knowis.cp.binding.topic:
topicBindings:
<Topic-Alias-1>:
topicName: "<Kafka topic name>"
kafkaBinding: "<Kafka-Secret-1>"
<Topic-Alias-2>:
topicName: "<Kafka topic name>"
kafkaBinding: "<Kafka-Secret-2>"
kafkaBindings:
<Kafka-Secret-1>:
kafka_brokers_sasl: ""
password: ""
user: ""
<Kafka-Secret-2>:
kafka_brokers_sasl: ""
password: ""
user: ""
ℹ️note

Kafka broker user and password are optional if your Kafka broker is not secured.

Swagger UI

To use a Swagger UI for local development, the Swagger UI Support extension needs to be enabled. You can enable the extension for your project via the extensions page in the Solution Designer.

After starting the application locally, the Swagger UI can be accessed from the following URL: localhost:8080/{service-acronym}/swagger-ui/index.html

💡tip

The Swagger UI URL is dependent on the configured path in your application.yaml or application-local.yaml. We recommend to set the value of springdoc.swagger-ui.path to /${solution.acronym}/swagger-ui to make use of the above described URL. If no specific value is set, the Swagger UI will be available under localhost:8080/swagger-ui/index.html

For proper usage of a clientId in the Swagger UI, please ensure that you use the following settings in your application-local.yaml:

springdoc:
swagger-ui:
oauth:
clientId: <client-id>

If you have spring-security-oauth2-client on your classpath, you can take advantage of some auto configuration to set up an OAuth2/Open ID Connect client, as shown in the following example:

spring:
security:
oauth2:
client: #Spring Security OAuth2 config
provider:
default:
issuer-uri: <issuer-uri>
<client-id>:
jwk-set-uri: <jwk-set-uri>
token-uri: <token-uri>
issuer-uri: <issuer-uri>
registration:
default:
client-id: <client-id>
<client-id>: # only required if the access type of the client is not public
client-id: <client-id>
client-secret: <secret>

Schema registry configurations

ℹ️note

How to configure a schema registry for local development, is depending on whether your project is based on Java Spring Boot Stack 1.0 or Java Spring Boot Stack 2.0

Java Spring Boot Stack 2.0

To configure a schema registry for local development, please use the following settings:

k5.sdk.springboot.schema-registry:
schemaRegistryConfig:
schemaRegistryUrl: <schema-registry-url>
schemaAuthServerUrl: <schema-auth-server-url>
authRealm: <auth-realm>
clientSecret: <client-secret-token>
clientId: <client-id>
Java Spring Boot Stack 1.0 (Deprecated)

To configure a schema registry for local development, please use the following settings:

de.knowis.schema-registry:
schemaRegistryConfig:
schemaRegistryUrl: <schema-registry-url>
schemaAuthServerUrl: <schema-auth-server-url>
authRealm: <auth-realm>
clientSecret: <client-secret-token>
clientId: <client-id>
ℹ️note

Please consider, that the LRA coordinator might not be able to trigger the callbacks if your service is running locally

Configure OAuth settings

As a fallback strategy, an additional client is required for the propagate JWT token feature.

To configure the additional client, please use the following settings (e.g. you can get the values from secret dashboard-oauth-client-secret:

spring:
security:
oauth2:
client:
provider:
<the_client_registration_id>:
token-uri: "<the_token_uri>"
jwk-set-uri: "<the_jwk_set_uri>"
registration:
<the_client_registration_id>:
client-id: "<the_client_id>"
client-secret: "<the_client_secret>"
authorizationGrantType: "client_credentials"
overwriteParameter:
audience: "<https://your-api.example.com>"
scope: "<custom-scope-value>"

k5:
sdk:
springboot:
oidc:
clientRegistrationId: "<the_client_registration_id>"
ℹ️note

For compatibility with different Identity Providers, you can specify additional parameters such as audience and scope using the overwriteParameter property. Some providers require a specific audience value to identify the intended API, and a custom scope to grant the necessary permissions. This allows flexible, provider-specific adjustments.

If your Identity Provider does not require additional parameters, you can simply omit the overwriteParameter section from the configuration.

Running with local profile

Create a new Run Configuration for a Java Application. Pass the configuration below as jvm arguments to use the local profile.

-Dspring.profiles.active=local
Further configurations
ℹ️note

This is only relevant for projects based on Java Spring Boot Stack 2.0

According to the following issue https://github.com/spring-projects/spring-data-mongodb/issues/4237, using date or dateTime properties in entities or root entities can cause problems. To mitigate this problem, please adjust your run configuration and add --add-opens=java.base/java.time=ALL-UNNAMED so that it looks like the following:

-Dspring.profiles.active=local --add-opens=java.base/java.time=ALL-UNNAMED

Build and run the code.

ℹ️note

Refer to Spring Boot's official documentation for more details on Database and Kafka additional configuration.