# Java

    Erda supports building capabilities through a unified task plugin mechanism, and provides Java building plugins out of the box.

    # Version

    The platform supports Java 1.8 and Java 11, with the former as default.

    # Packaging Tool

    • Maven
    • Gradle

    # Dependency Management

    If you use the configuration file provided by the platform, you do not need to modify the code. The following files are ready with placeholders filled in.

    • Maven: settings.xml
    • Gradle: init.gralde

    An example of settings.xml is as follows:

    <?xml version="1.0" encoding="UTF-8"?>
    <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
        <servers>
            <server>
                <id>terminus</id>
                <username>{{NEXUS_USERNAME}}</username>
                <password>{{NEXUS_PASSWORD}}</password>
            </server>
        </servers>
        <mirrors>
            <mirror>
                <id>terminus</id>
                <mirrorOf>*</mirrorOf>
                <url>{{NEXUS_URL}}/repository/public/</url>
            </mirror>
        </mirrors>
    
        <profiles>
            <profile>
                <activation>
                    <activeByDefault>true</activeByDefault>
                </activation>
                <repositories>
                    <repository>
                        <id>placeholder</id>
                        <url>{{NEXUS_URL}}/repository/public/</url>
                        <releases>
                            <enabled>true</enabled>
                        </releases>
                        <snapshots>
                            <enabled>true</enabled>
                            <updatePolicy>always</updatePolicy>
                            <checksumPolicy>warn</checksumPolicy>
                        </snapshots>
                    </repository>
                </repositories>
                <pluginRepositories>
                    <pluginRepository>
                        <id>placeholder</id>
                        <url>{{NEXUS_URL}}/repository/public/</url>
                        <releases>
                            <enabled>true</enabled>
                        </releases>
                        <snapshots>
                            <enabled>true</enabled>
                            <updatePolicy>always</updatePolicy>
                            <checksumPolicy>warn</checksumPolicy>
                        </snapshots>
                    </pluginRepository>
                </pluginRepositories>
            </profile>
        </profiles>
    </settings>
    

    An example of init.gradle is as follows:

    def NEXUS_SERVER = "{{NEXUS_URL}}/repository/public/"
    def NEXUS_USERNAME = "{{NEXUS_USERNAME}}"
    def NEXUS_PASSWORD = "{{NEXUS_PASSWORD}}"
    
    allprojects {
        buildscript {
            repositories {
                maven {
                    credentials {
                        username NEXUS_USERNAME
                        password NEXUS_PASSWORD
                    }
                    url NEXUS_SERVER
                }
            }
        }
        repositories {
            maven {
                credentials {
                    username NEXUS_USERNAME
                    password NEXUS_PASSWORD
                }
                url NEXUS_SERVER
            }
        }
    }
    

    # Push JAR Package to Private Server

    # Upload Maven settings.xml

    Go to My Application > Select Application > Setting > Pipeline > Variable Configuration > Select Environment.

    Click Add Variable, select the type as File and enable encryption, then upload settings.xml and define the variable name as MAVEN_SETTING_FILE.

    Warning

    Encryption is required as the file includes sensitive information such as passwords.

    An example of settings.xml is as follows:

    <?xml version="1.0" encoding="UTF-8"?>
    
    <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
    
      <servers>
        <server>
          <id>terminus</id>
          <username>deployment</username>
          <password>******</password>
        </server>
      </servers>
    </settings>
    

    # Configure Push Address of pom.xml

    Add the following configuration to pom.xml of the corresponding project, otherwise it cannot be pushed.

    <distributionManagement>
        <repository>
            <id>terminus</id>    <!-- server.id configured in settings.xml -->
            <name>Releases</name>
            <url>http://private server address/repository/releases</url>  <!-- release private server address -->
        </repository>
        <snapshotRepository>
            <id>terminus</id>
            <name>Snapshots</name>
            <url>http://private server address/repository/releases</url>  <!-- snapshot private server address -->
        </snapshotRepository>
    </distributionManagement>
    

    # Configure Pipeline to Upload JAR Package

    MAVEN_SETTING_FILE is the name configured above.

    version: "1.1"
    
    stages:
    - stage:
      - git-checkout:
          alias: git-checkout
          params:
            depth: 1
    - stage:
      - java-build:
          alias: java-build
          version: "1.0"
          params:
            build_cmd:
               - "rm -rf /usr/share/maven/conf/setting.xml"
               - "mvn clean deploy  -e -B -U --settings ((MAVEN_SETTING_FILE)) -Dmaven.test.skip"
            jdk_version: 8
            workdir: ${git-checkout}
    

    Add configuration of continuous integration (CI) if automated building is required.

    on:
      push:
        branches:
          - develop # Continuous integration
    

    Tips

    • 401 in Maven indicates incorrect password.
    • 405 in Maven possibly indicates incorrect private server address, as some private server addresses cannot be pushed, such as public.

    # Push JAR Package to Private Server (Gradle)

    # Configure Password of Nexus Private Server

    Go to My Application > Select Application > Setting > Pipeline > Variable Configuration > Select Environment.

    Click Add Variable, select the type as Value and enable encryption, then configure the following variables:

    • NEXUS_USERNAME
    • NEXUS_PASSWORD

    Warning

    Encryption is required as the file includes sensitive information such as passwords.

    # Configure Push Address of build.gradle

    Add the following configuration to build.gradle of the corresponding project, otherwise it cannot be pushed. For more information, see Configuration of build.gradle (opens new window).

    publishing{
    
        ...
    
        repositories {
            maven {
                // change URLs to point to your repos, e.g. http://my.org/repo
                def releasesRepoUrl = "http://private server address/repository/releases"
                def snapshotsRepoUrl = "http://private server address/repository/snapshots"
                url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
                credentials {
                    username = System.getenv("NEXUS_USERNAME")
                    password = System.getenv("NEXUS_PASSWORD")
                }
            }
        }
    }
    

    # Configure Pipeline to Upload JAR Package

    version: "1.1"
    
    stages:
    - stage:
      - git-checkout:
          alias: git-checkout
          params:
            depth: 1
    - stage:
      - java-build:
          alias: java-build
          version: "1.0"
          params:
            build_cmd:
               - "./gradlew publish"
            jdk_version: 8
            workdir: ${git-checkout}
    

    Add configuration of continuous integration (CI) if automated building is required.

    on:
      push:
        branches:
          - develop # Continuous integration
    

    Tips

    • 401 in Maven indicates incorrect password.
    • 405 in Maven possibly indicates incorrect private server address, as some private server addresses cannot be pushed, such as public.

    # Access Log

    As the platform only collects logs exported to the console, so the application needs to import logs into the console.

    Warning

    Do not write logs into disk files, which may lead to serious problems such as performance degradation or disk resource exhaustion.

    Export logs to the console with Logback configuration:

    <?xml version="1.0" encoding="UTF-8"?>
    <configuration scan="true" scanPeriod="30 seconds">
        <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
                <pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSZZ} [%thread] %-5level %logger{5} - %msg%n</pattern>
            </encoder>
        </appender>
        <root level="DEBUG">
            <appender-ref ref="CONSOLE"/>
        </root>
    </configuration>
    

    If the container provided by the platform is used, the platform will automatically close the appenders other than ConsoleAppender such as RollingFileAppender to ensure that the log cannot be written to disk. Please confirm that the ConsoleAppender is configured, otherwise you cannot view the log.

    # Building and Packaging

    Java building consists of two parts:

    1. Compile the source code into a packaged product by specified packaging method and context parameters.
    2. Select images to make JAR package into an operating image according to specified running environment and version.

    Tips

    It is called packaged product rather than JAR package because of compilation results. For example, traditional Spring MVC program produces WAR package, while gradle distribution produces Tar or ZIP package, run by bin/xxx.

    The JAR package made by Spring Boot is called fat jar, as all dependencies except the Java virtual machine are embedded in the JAR package.

    Since the fat jar is an all-in-one JAR package, it can run by java -jar app.jar in the Java virtual machine environment.

    An example of pipeline.yml is as follows:










     



     

    version: "1.1"
    
    stages:
    - stage:
      - git-checkout:
    
    - stage:
      - java:
          params:
            build_type: maven
            workdir: ${git-checkout}
            options: -am -pl user
            target: ./user/target/user.jar
            container_type: openjdk
    

    # Packing Acceleration

    # Gradle

    Comes with Gradle cache node, which is enabled by default.

    # Caches

    An example is as follows:

    - stage:
      - java:
          caches:
            - path: /root/.m2/repository
          params:
            build_type: maven
            workdir: ${git-checkout}
            options: -am -pl user
            target: ./user/target/user.jar
            container_type: openjdk
    

    The directory of /root/.m2/repository is the address of the Maven local repository in Linux, and the building can be accelerated after caching.

    # JVM Diagnosis

    # Arthas

    Arthas can be installed via the curl -sf https://arthas.aliyun.com/arthas-boot.jar -o arthas-boot.jar command.

    After the installation is successful, according to the installation directory, execute the java -jar arthas-boot.jar command to start.

    For more information on Arthas, see Arthas Documentation (opens new window).

    # Greys

    If you use the container provided by the platform, Greys is already installed.

    For more information on Greys, see Greys Documentation (opens new window).

    # Remote Debugging & Hot Update

    The platform provides VPNs for local and remote connection to services running on the platform.

    To enable remote debugging, go to My Application > Select Application > Setting > Pipeline > Variable Configuration, and add variable configuration for JAVA_OPTS as follows:

    JDK 9 and later:

    JAVA_OPTS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
    

    JDK 5~8:

    JAVA_OPTS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
    

    In addition, if a local IDE is needed, go to DevOps Platform > App Center > Environments to find the container IP, and configure in the IDE as follows:

    JDK 9 and later:

    JDK 5~8: