22 Ağustos 2023 Salı

Conflicting Transitive Dependency

Giriş
İstenilen transitive dependency sürümünü tanımlamak için kullanılabilir. Açıklaması şöyle. 
The point of dependencyManagement is to allow me to specify a version for transitive dependencies. 
Örnek
Şöyle yaparız
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>conflicting.group</groupId>
      <artifactId>TransitiveDependency</artifactId>
      <version>desired.version</version>
    </dependency>
  </dependencies>
</dependencyManagement>
Örnek - BOM
Şöyle yaparız. Burada Log4J2 için BOM kullanılıyor. Böylece tüm projedeki log4j sürümü değiştirilebiliyor.
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-bom</artifactId>
      <version>${log4j2.version}</version>
      <scope>import</scope>
      <type>pom</type>
    </dependency>
  </dependencies>
</dependencyManagement>

Örnek
Bir projede snakeyaml kütüphanesinin eski bir sürümü  transitive dependency olarak gelsin ama biz daha yeni bir sürüm kullanmak isteyelim. Şöyle yaparız
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.yaml</groupId>
      <artifactId>snakeyaml</artifactId>
      <version>1.32</version>
    </dependency>
  </dependencies>
</dependencyManagement>

13 Ağustos 2023 Pazar

Apache Ant

Giriş
Açıklaması şöyle
Ant is based on three main abstractions:

- A task is an atomic unit of work, e.g., javac to compile Java files, war to assemble a Web Archive, etc. Ant provides lots of tasks out-of-the-box but allows adding custom ones.
- A target is a list of tasks
- You can define dependencies between tasks, such as package depending on compile. In this regard, you can see Ant as a workflow execution engine.

31 Temmuz 2023 Pazartesi

25 Temmuz 2023 Salı

mvn komutu -pl seçeneği - Project List

Giriş
Multi-module projelerde kullanılır. "project list" anlamına gelir. Tüm projeleri değil sadece ismi belirtilen projeyi derler. Açıklaması şöyle.
-pl,--projects <arg> >> Comma-delimited list of specified reactor projects to build
  instead of all projects. A project can be specified by [groupId]:artifactId or by its
  relative path.
Örnek
Şöyle yaparız.
mvn package -pl sub_module
Örnek
Şöyle yaparız. Burada module ismi gateway ve spring-boot plugin'i tetikleniyor. 
mvn -pl gateway spring-boot:run 
-DskipTests
-Dspring-boot.run.arguments= — EUREKA_SERVER_ADDRESS=http://localhost:8761/eureka
Örnek - exlude
Şöyle yaparız. Burada - veya ! karakteri ile bazı modüllerin hariç bırakılması sağlanıyor
mvn install -DskipTests -pl -distribution,-extensions/hadoop-dist -f pom.xml

-amd ile Birlikte Kullanımı - also-make-dependents
Açıklaması şöyle
The -amd option stands for "also-make-dependents" and is used along with -pl to ensure that not only the specified modules are built but also the projects that depend on them.
Örnek
Bu modüle bağımlı olan diğerlerini de derlemek için şöyle yaparız.
mvn clean package -pl sub_module -amd
-am ile Birlikte Kullanımı - also-make
Açıklaması şöyle
The -am option stands for "also-make" and is used along with -pl to ensure that not only the specified modules are built but also their dependencies.
Örnek
Belirtilen modülün kullandığı diğer modülleri de derlemek istersek şöyle yaparız.
mvn clean package -pl sub_module -am

18 Temmuz 2023 Salı

dockerfile plugin

Giriş
Açıklaması şöyle
Spotify Dev team open-sourced many tools they are using among others dockerfile-maven-plugin as well.

The dockerfile-maven-plugin can create and publish a docker image based on your Dockerfile meanwhile running maven commands.

It allows you to configure the props based on your need. The usage doc can be found here. Authentication doc for publishing your app’s image to Google Cloud Container or your registry can be found here.
Örnek
Şöyle yaparız
<plugin>
  <groupId>com.spotify</groupId>
  <artifactId>dockerfile-maven-plugin</artifactId>
  <version>${dockerfile-maven-plugin.version}</version>
  <configuration>
    <repository>${docker.image.prefix}/${project.artifactId}</repository>
  </configuration>
  <executions>
    <execution>
      <id>default</id>
      <phase>install</phase>
      <goals>
        <goal>build</goal>
      </goals>
    </execution>
  </executions>
</plugin>
Docker dosyası için şöyle yaparız.  maven install komutu ile önce jar yapılandırılıyor. En son olarak ta Docker dosyası çalıştırılıyor
FROM openjdk:17-alpine as builder

WORKDIR application

ARG JAR_FILE=target/*.jar

COPY ${JAR_FILE} application.jar
RUN java -Djarmode=layertools -jar application.jar extract

FROM openjdk:17-alpine
WORKDIR application
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
COPY --from=builder application/snapshot-dependencies/ ./
COPY --from=builder application/application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]
mvn deploy ile de Docker image Docker deposuna gönderilir

17 Temmuz 2023 Pazartesi

shade plugin - relocation Kullanımı

Giriş
Bazen bir kütüphane ile gelen 3. taraf bağımlılıklar ile kendi projem arasında uyumsuzluk olur.  

1. relocation Alanı
relocation ve shadedPattern genelde birlikte kullanılır

Örnek
Şöyle yaparız. Burada org.apache.calcite kodları başka bir dizinine toplanır
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <configuration>
    <shadedArtifactAttached>false</shadedArtifactAttached>
    <relocations>
      <relocation>
        <pattern>org.apache.calcite</pattern>
        <shadedPattern>${relocation.root}.org.apache.calcite</shadedPattern>
      </relocation>
    </relocations>
  </configuration>
</plugin>
Örnek
Şöyle yaparız. 
- Burada joda-time ve com.amazonaws kütüphanelerini dahil eden bir fat jar üretiliyor. 
- Ayrıca org.joda paketleri com.amazonaws.thirdparty.joda altına taşınıyor.
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <version>2.4.3</version>
  <configuration>
    <artifactSet>
      <includes>
        <include>joda-time:joda-time</include>
        <include>com.amazonaws:*</include>
      </includes>
    </artifactSet>
    <relocations>
      <relocation>
        <pattern>org.joda</pattern>
        <shadedPattern>com.amazonaws.thirdparty.joda</shadedPattern>
      </relocation>
    </relocations>
  </configuration>
</plugin>
Örnek
Şöyle yaparız
<plugin>
  <artifactId>maven-shade-plugin</artifactId>
  <configuration>

    <!-- Cancel the relocation of jackson-core defined in parent pom.
    <relocations combine.self="override">
    </relocations>
  </configuration>
</plugin>
veya şöyle yaparız
<plugin>
  <artifactId>maven-shade-plugin</artifactId>
  <configuration>

    <!-- Cancel the relocation of jackson-core defined in hazelcast-parent pom.
    <relocations combine.self="override">
      <relocation>
        <pattern>com.fasterxml.jackson.core</pattern>
        <shadedPattern>com.fasterxml.jackson.core</shadedPattern>
      </relocation>
    </relocations>
  </configuration>
</plugin>
2. Sadece shadedPattern Alanı
Açıklaması şöyle. Kendi kodlarım ve dependency olarak gelen kütüphaneler shade isimli bir dizine toplanır. İstenirse bu dizine yeni bir isim verilebilir
The "shadedPattern" is a configuration option in the Maven Shade Plugin that specifies the pattern for renaming the classes and resources in the shaded JAR file.

When you use the Maven Shade Plugin to create a shaded JAR, it merges all the dependencies of your project into a single JAR file. During the shading process, the plugin renames the classes and resources from the original JAR files to avoid conflicts with other libraries in the classpath.

The shadedPattern option allows you to specify the pattern for the renamed classes and resources in the shaded JAR. By default, the pattern is "shade/[class]", which means that all classes and resources will be moved to a "shade" directory in the JAR file.

You can customize the shadedPattern option to change the directory structure or add prefixes or suffixes to the renamed classes and resources. For example, you could use the pattern "myapp/[artifactId]-[version]/[class]" to create a directory structure that includes the name and version of your project.
Örnek
Şöyle yaparız. Burada kendi kodlarım da dahil olmak üzere her şey myapp/my-app-1.0.0/ dizinine toplanır
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <version>3.2.4</version>
  <configuration>
    <shadedPattern>myapp/[artifactId]-[version]/[class]</shadedPattern>
  </configuration>
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>shade</goal>
      </goals>
    </execution>
  </executions>
</plugin>

15 Haziran 2023 Perşembe

jacoco CLI Komut Satırından Çalıştırmak

dump seçeneği
Şöyle yaparız. Burada sırayla her POD üzerindeki JaCoCo agent'a bağlanıyor ve dump seçeneği ile dosyayı alıyor. Daha sonra merge seçeneği ile dosyaları birleştiriyor
#!/usr/bin/env bash

set -e -u -o pipefail

if [ "${#}" -lt 4 ]; then
  echo "Usage: ${0} <path-to-jacococli.jar> <kubernetes-context> <kubernetes-namespace> <kubernetes-pod-selector>"
  echo "For selector syntax, see https://kubernetes.io/docs/concepts/overview/working-with-objects/labels."
  exit 1
fi

JACOCO_CLI_LOCAL="$(realpath "${1}")"
CONTEXT="${2}"
NAMESPACE="${3}"
POD_SELECTOR="${4}"

# All resources are stored in a temporary directory.
TMP_DIR='/tmp/jacoco-export'
mkdir -p "${TMP_DIR}"
pushd "${TMP_DIR}"

# Fetch coverage data from all pods.
kubectl get pods \
  --context="${CONTEXT}" \
  --namespace="${NAMESPACE}" \
  --selector="${POD_SELECTOR}" \
  --no-headers \
  -o custom-columns=":metadata.name" \
  | while read POD; do
    # One pod at a time, open a tunnel, connect to the JaCoCo agent to fetch
    # the coverage data and close the tunnel again.
    echo $CONTEXT - $POD
    (
      kubectl port-forward \
        --context="${CONTEXT}" \
        --namespace "${NAMESPACE}" \
        "${POD}" \
        "6300:6300" &
      trap "kill ${!}" ERR EXIT HUP INT TERM
      java -jar "${JACOCO_CLI_LOCAL}" dump --destfile "jacoco-${POD}.exec"
    )
  done

# Merge the coverage data into a single file.
java -jar "${JACOCO_CLI_LOCAL}" merge --destfile jacoco.exec jacoco-*.exec
popd
report seçeneği
Örnek
Dosyayı HTML olarak formatlamak için şöyle yaparız
java -jar jacococli.jar report jacoco.exec [options]
Örnek
Şöyle yaparız.
#!/usr/bin/env bash

set -e -u -o pipefail

if [[ "${#}" -lt 2 ]]; then
  echo "Usage: ${0} <path-to-jacococli.jar> [--sourcefiles-matcher=<string>] [ --classfiles-miles-matcher<string>] <source-roots>..."
  exit 1
fi

JACOCO_CLI_LOCAL="$(realpath "${1}")"
shift
SOURCEFILES_MATCHER='*/src/main/java'
CLASSFILES_MATCHER='*/target/classes'

while [ "${#}" -gt 0 ]; do
  case "${1}" in
  --sourcefiles-matcher)
    shift
    SOURCEFILES_MATCHER="${1}"
    ;;
  --classfiles-matcher)
    shift
    CLASSFILES_MATCHER="${1}"
    ;;
  *)
    break
    ;;
  esac
done

if [[ "${#}" -ne 1 ]]; then
  echo "No source roots passed."
  exit 1
fi


pushd /tmp/jacoco-export

# Generate an HTML report based on the collected data. Note that this command
# assumes that the associated source code has been compiled (i.e. that the
# `target/classes` directories are present and populated).
java -jar "${JACOCO_CLI_LOCAL}" report jacoco.exec --html report \
  $(find "${@:1}" -path "${CLASSFILES_MATCHER}" | sed 's/^/--classfiles /') \
  $(find "${@:1}" -path "${SOURCEFILES_MATCHER}" | sed 's/^/--sourcefiles /')

popd

mvnup komutu

check Şöyle yaparız mvnup check apply Şöyle yaparız mvnup apply