You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
String'in implicit tip olduğunu hatırlıyorum. Eskiden kıyaslarken String.equals(string str) gibi bir method kullanlıyordu, hala böyle mi. Bi yerde 2 eşit kullanabiliyor gibi görmüştüm. Bu olay JDK veriyonları arasında breaking changes olarak mı geçti acaba ??
Bundan sonra teminali kapatmak gerekiyor galiba, en azından WSL'de böyle oldu. Altaki kodu hemen görmemişti.
java -version
openjdk version "21.0.1" 2023-10-17 LTS
OpenJDK Runtime Environment Corretto-21.0.1.12.1 (build 21.0.1+12-LTS)
OpenJDK 64-Bit Server VM Corretto-21.0.1.12.1 (build 21.0.1+12-LTS, mixed mode, sharing)
javac -version
javac 21.0.1
Başka versiyon kuralım
sdk install java 21-open
Gradle gibi toolları da buradan kurabiliyormuşuz..
sdk install gradle
gradle --help
Gradle'la da bakalım birazcık
gradle init (bunu başka projede deniyorum)
Select type of project to generate:
1: basic
2: application
3: library
4: Gradle plugin
Enter selection (default: basic) [1..4] 1
Select build script DSL:
1: Kotlin
2: Groovy
Enter selection (default: Kotlin) [1..2] 2
Project name (default: learning-java):
Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no] no
> Task :init
To learn more about Gradle by exploring our Samples at https://docs.gradle.org/8.5/samples
BUILD SUCCESSFUL in 9s
2 actionable tasks: 2 executed
Mümkün olduğunca en basic halini seçtim ve beklediğimden daha fazla dosya oluşmuş oldu.
Dosyalar şöyle
gradlew ve gradlew.bat
gradlew bir bash script. gradlew.bat ise aynısının windows friendly hali
settings.gradle ve build.gradle DSL script ile hazırlanmış. Ne için kullanılıyor tam olarak hakim değilim.
gradle/wrapper/gradle-wrapper.jar yaklaşık 43KB olan bir dosyamız. Defualt olarak .gitignore'a eklenmemiş.
Gradle ile basic console app deneyelim.
gradle init
Select type of project to generate:
1: basic
2: application
3: library
4: Gradle plugin
Enter selection (default: basic) [1..4] 2
Select implementation language:
1: C++
2: Groovy
3: Java
4: Kotlin
5: Scala
6: Swift
Enter selection (default: Java) [1..6] 3
Generate multiple subprojects for application? (default: no) [yes, no] no
Select build script DSL:
1: Kotlin
2: Groovy
Enter selection (default: Kotlin) [1..2] 2
Select test framework:
1: JUnit 4
2: TestNG
3: Spock
4: JUnit Jupiter
Enter selection (default: JUnit Jupiter) [1..4] 1
Project name (default: learning-java):
Source package (default: learning.java):
Enter target version of Java (min. 7) (default: 21):
Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no] no
> Task :init
To learn more about Gradle by exploring our Samples at https://docs.gradle.org/8.5/samples/sample_building_java_applications.html
BUILD SUCCESSFUL in 1m 19s
2 actionable tasks: 2 executed
Bu şekilde run edebileceğimiz komutlar var.
run etmek için
./gradlew run
tasklar var örnek kodlarımız
./gradlew tasks
./gradlew tasks --all
test build
./gradlew build
./gradlew jar
./gradlew help --task build
test için
./gradlew test
./gradlew help --task test
Ufak derin bilgilerden
CWD ve ./gradlew run ilişkisi
file formatlarıyla falan çalışmamız gerektiği durumlarda CWD kullanmamız gerekir. Java en nihayetinde compile oluyor ve single file'a dönüyor. nodejs'de __dirname ve __filename gibi değişkenleri kullanabiliyorduk ama burada pek mantıklı değil gibi duruyor.
CWD için JAVA'da kullanılan kod şöyle
String cwd = System.getProperty("user.dir");
gradle ile run ettiğimizde CWD değeri farklı geliyor. Çünkü gradle, projeyi build ettikten sonra app dizine gidiyor ve projeyi orada run ediyor.
nasıl test ederiz peki
./gradlew build yada ./gradlew jar
java -jar ./app/build/libs/app.jar
muhtemelen şu şekilde hata alacağız.
no main manifest attribute, in ./app/build/libs/app.jar
Bunun çözümü için, build.gradle'a jar için Main-Class propertisini girmek gerekiyor.
CWD ile alakalı sorun yaşıyorduk ve hala yaşıyoruz.
Örnekteki koda göre projenin ana dizini için bu path'i varsayalım --> ~
// ~/app/example.json // ./gradlew CWD olarak hep app'in içinde.// ~/example.json // build edildikten sonra .jar file CWD'yi düzgün gördüğü için bunu kullanıyor
{
"id": 151,
"name": "ALİ",
"surname": "Duru"
}
BUILD SUCCESSFUL in 1s
7 actionable tasks: 6 executed, 1 up-to-date
jsonContent: {
"id": 151,
"name": "ALİ",
"surname": "Duru"
}
Exception in thread "main" java.lang.NoClassDefFoundError: com/google/gson/Gson
at learning.java.App.readFromJson(App.java:71)
at learning.java.App.main(App.java:88)
Caused by: java.lang.ClassNotFoundException: com.google.gson.Gson
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526)
... 2 more
MAVEN
gradle'a ara verdik, bi de maven ile denemeler yapalım...
FAT JAR kavramı ve .jar dosyasını execute işlemi
Dependency'leri de içeriyorsa buna FAT JAR diyorlar.
Bu konu ciddi bir konu. Dependency kullandığımızda build ettiğimiz app'i run ettiğimizde patlıyoruz. Development'ta çalışmasına rağmen build (.jar dosyası) dependency'ileri bulamıyor.
Benim anladığım, dependency'i import etmek için 2 yöntem var. Birisini maven developmentta iken kendisi handle ediyor ve ~/.m2 folderından import ediyor. Compile ederken javac'ı dependenciler için kullanmıyor olabilir, sadece yazdığımız kod için kullanıyordur muhtemelen. Ama compile edilmiş kod'u run ederken birden fazla .jar dosyası verebiliyor (Böyle çok kod gördüm Örnek: java -cp lib\*.jar;. myproject.MainClass). Bu yönteme fat jar Demiyoruz. Çünkü hepsi ayrı ayrı jar dosyaları. Ve henüz bunun nasıl yapıldığını bilmiyorum. Bir şekilde depend olan kütüphanenin jar dosyalarını target'ın içine kopyalayabilirsem olurdu ama henüz öğrenemedim :)
Peki FAT JAR nasıl yapılıyor. Bu zıkkım için de plugin işine girmemiz gerekiyor. Pluginimizin adı; maven-assembly-plugin
mvn clean compile assembly:single yazıyoruz. İsmi, mvn package'ı run ettiğimizden daha farklı bir .jar dosyası çıkartıyor. Kıysalamak için mvn clean package assemly:single'ı run edebilirsiniz.
İşin güzel tarafından biri de, bu jar dosyasının mainClass'ı tanımlamış oluyor. Direk şu şekilde çalıştırabiliyoruz. mainClass değeri default olarak verilmiş oluyor, yani run ederken -cp ile 2. parametrede verebiliyoruz.
Bu satırı ekliyoruz. Bu sayede default mainClass'ı belirlemiş oluyoruz. Bu string değeri jar dosyasının içine yazılmıyor diye anlıyorum. build edilmiş jar dosyasını run ederken gene de bu veriyi vermemiz gerekiyor
Hala build alından dosyadan kütüphane'ye erişemiyorduk. FAT JAR hazırlamayı öğrendik, yukarıyı oku.
Gradle'da oluğu gibi
Fat olmayan JAR file run ederken potansiyel hata
Not, henüz bunu hazırlamayı bilmiyorum.
# Execute jar file with multiple classpath libraries from command prompt# https://stackoverflow.com/a/25156085/7975831# Using java 1.7, on UNIX -# on UNIX
java -cp myjar.jar:lib/*:. mypackage.MyClass
# On Windows you need to use ';' instead of ':' -
java -cp myjar.jar;lib/*;. mypackage.MyClass