21 Haziran 2023 Çarşamba

HttpClient Sınıfı İle Connect Pool - HttpClient API

Giriş
Açıklaması şöyle
The Java 11 HttpClient has an internal connection pool. By default, it is unlimited in size.
Açıklaması şöyle
The JDK 11 ConnectionPool checks the jdk.httpclient.connectionPoolSize system property when initializing and defaults to 0 (unlimited).
Örnek
Şöyle yaparız
HttpClient client = HttpClient.newBuilder()
    .connectionPool(ConnectionPool.newBuilder()
        .maxConnections(50)
        .build())
    .build();

20 Haziran 2023 Salı

HttpClient Sınıfı İle POST

Giriş
Java 11 ile artık HttpsURLConnection, HttpURLConnection sınıfları yerine HttpClient kullanılıyor. Burada bazı örnekler var.

Örnek
Şöyle yaparız. Burada String verisi POST yapılıyor ama cevap önemli değil, dikkate alınmıyor 
HttpRequest httpRequest = HttpRequest.newBuilder()
  .uri(URI.create(basePhoneHomeUrl))
  .timeout(Duration.ofMillis(TIMEOUT))
  .POST(HttpRequest.BodyPublishers.ofString(requestBody, StandardCharsets.UTF_8))
  .build();

try {
  HttpClient httpClient = HttpClient.newBuilder()
    .connectTimeout(Duration.ofMillis(TIMEOUT))
    .build();

    httpClient.send(httpRequest, HttpResponse.BodyHandlers.discarding());
} catch (Exception ignored) {
  ...
}
Örnek
Şöyle yaparız. Burada JSON verisi POST yapılıyor ve cevap dikkate alınıyor
HttpResponse<String> postData(String jsonStr, String endpoint, String accessToken) throws Exception { HttpClient httpClient = HttpClient.newHttpClient(); HttpRequest httpRequest = HttpRequest.newBuilder() .header("Content-Type", "application/json") .header("Authorization", "Bearer " + accessToken) .uri(URI.create("https://...")) .POST(HttpRequest.BodyPublishers.ofString(jsonStr)) .build(); HttpResponse<String> httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); return httpResponse; }

RecordingStream Sınıfı - Flight Recorder - Java 11 İle Geliyor

Giriş
Şu satırı dahil ederiz
import jdk.jfr.consumer.RecordingStream;
Örnek
Şöyle yaparız
import jdk.jfr.consumer.RecordingStream;

public static void main(String[] args) {
  try (var rs = new RecordingStream()) {
    rs.onEvent("jdk.GarbageCollection", event ->
      System.out.format("Garbage collection: %s, duration: %dns%n", event.getEndTime(), event.getDuration())
  );

    rs.startAsync();
    Thread.sleep(60_000);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
}
Açıklaması şöyle
In this example, we create a RecordingStream, define an event handler for garbage collection events, start the stream asynchronously, and keep the application alive for 60 seconds to observe the events.

HttpResponse Sınıfı - Java 11 İle Geliyor - HttpClient API

Giriş
Şu satırı dahil ederiz
import java.net.http.HttpResponse;
body metodu
 HttpResponse.BodyHandlers.ofString() veya bir türevi ile cevap çözüldükten sonra cevabın içeriğine body() metodu ile erişebiliriz
Örnek
Şöyle yaparız
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

HttpClient httpClient = HttpClient.newHttpClient();

HttpRequest request = HttpRequest.newBuilder()
  .uri(URI.create("https://api.example.com/data"))
  .GET()
  .build();

HttpResponse<String> response = httpClient .send(request, HttpResponse.BodyHandlers.ofString());

System.out.println(response.statusCode());
System.out.println(response.body());

JEP 323 - Improved var Handling

Giriş
Lambda içinde değişkene tip yerine var kullanılabilir.

Örnek
Şöyle yaparız
// Pre-Java 11
Function<String, Integer> preJava11Func = (String s) -> Integer.parseInt(s) + 10;

// Java 11
Function<String, Integer> java11Func = (var s) -> Integer.parseInt(s) + 10;

JEP 330 - Running Java Files Directly - Java 11 İle Geliyor

Giriş
Java 11'den itibaren derlemeden bazı dosyaları çalıştırmak mümkün. Açıklaması şöyle. Artık .class dosyası oluşmuyor.
Since Java 11, java FileName.java compiles and runs FileName.java; however, compilation happens "behind the scenes", without explicitly producing corresponding .class file. Instead, it directly loads corresponding byte-code into the JVM instance.
Örnek
Elimizde şöyle bir kod olsun.
public class Myclass {
 public  static void main(String[] args){
    System.out.println("hello world");
  }
}
Eskiden şöyle yapardık
javac hello.java
java hello
Şimdi sadece şöyle yaparız.
$ java hello.java
$ hello world
Örnek
Şöyle yaparız
java --source 21 --enable-preview MyAwesomeApp.java


19 Haziran 2023 Pazartesi

Javafaker

Maven
Şu satırı dahil ederiz
<dependency>
  <groupId>com.github.javafaker</groupId>
  <artifactId>javafaker</artifactId>
  <version>1.0.2</version>
</dependency>
Örnek
Şöyle yaparız
Faker faker = new Faker(Locale.FRANCE);

String teamName = faker.team().name();

faker.address().city();
faker.address().zipCode();
faker.address().streetAddress();

faker.name().firstName();
faker.name().lastName();

faker.date().birthday(18, 38);
faker.random().nextInt(0, 20)
faker.random().nextBoolean()

15 Haziran 2023 Perşembe

FileChannel.transferTo metodu - Zero Copy

Giriş
Source Channel nesnesinden, Destination Channel nesnesine kopyalama yapar. 

Zero Copy Nedir?
 Açıklaması şöyle
Zero Copy is a technique employed in computer systems to minimize data copying and movement during data transfer operations. It aims to improve performance and reduce resource utilization by avoiding unnecessary data copying.
Zero Copy Nasıl Yapılır?
 Açıklaması şöyle
The Java class libraries support zero copy on Linux and UNIX systems through the transferTo() method in java.nio.channels.FileChannel. You can use the transferTo() method to transfer bytes directly from the channel on which it is invoked to another writable byte channel, without requiring data to flow through the application.
Örnek - Dosyadan Dosyaya Kopyalama
FileChannel nesnesinden FileChannel nesnesine kopyalanır
Örnek
Şöyle yaparız.
void fileCopyUsingNIOChannelClass() throws IOException {
  File fileToCopy = new File("c:/temp/testoriginal.txt");
  FileInputStream inputStream = new FileInputStream(fileToCopy);
  FileChannel inChannel = inputStream.getChannel();

  File newFile = new File("c:/temp/testcopied.txt");
  FileOutputStream outputStream = new FileOutputStream(newFile);
  FileChannel outChannel = outputStream.getChannel();

  inChannel.transferTo(0, fileToCopy.length(), outChannel);

  inputStream.close();
  outputStream.close();
}
Örnek - Dosyadan Sockete Kopyalama
FileChannel nesnesinden SocketChannel nesnesine kopyalanır. Şöyle yaparız. İstemci bir sunucuya dosya gönderiyor
String host = "localhost";
int port = 9026;
SocketAddress socketAddress = new InetSocketAddress(host, port);
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(socketAddress);
socketChannel.configureBlocking(true);
String fname = ...; long fsize = 183678375L; FileChannel fileChannel = new FileInputStream(fname).getChannel(); long sentBytes = fileChannel.transferTo(0, fsize, socketChannel);
fileChannel.close();


14 Haziran 2023 Çarşamba

ToxiproxyContainers ToxiproxyContainer Sınıfı

Maven
Şu satırı dahil ederiz
<dependency>
<groupId>org.testcontainers</groupId> <artifactId>toxiproxy</artifactId> <version>1.18.3</version> <scope>test</scope> </dependency>
ToxiproxyClient Sınıfı
ToxiproxyContainer kullanılarak yaratılır

latency metodu
Örnek
Şöyle yaparız
import eu.rekawek.toxiproxy.Proxy;
import eu.rekawek.toxiproxy.ToxiproxyClient;
import eu.rekawek.toxiproxy.model.ToxicDirection;

@Testcontainers
public class ToxiproxyExample {

  @Container
  private static ToxiproxyContainer toxiproxy = new ToxiproxyContainer();

  @Container
  private static PostgreSQLContainer<?> database = new PostgreSQLContainer<>("postgres:11.19-bullseye")

  @Rule
  public ToxiproxyClient toxiproxyClient = new ToxiproxyClient(toxiproxy.getHost(), toxiproxy.getControlPort());
   
  @Test
  public void testApplicationWithLatency() {
    // ToxicDirection.DOWNSTREAM is from client to DB
    // Create a toxic that adds 100 milliseconds of latency to the connection to the DB.
    toxiproxyClient.toxics().latency("database", ToxicDirection.DOWNSTREAM, 100);

    // Try to connect to the database.
    try (var connection = DriverManager.getConnection(database.getHost() + ":" + database.getMappedPort(5432), "postgres", "postgres")) {
        // Do something with the connection.
    }
    // Remove the toxic.
    toxiproxyClient.toxics().get("database").remove();
  }
}


12 Haziran 2023 Pazartesi

ExecutionException Sınıfı

Giriş
Şu satırı dahil ederiz
import java.util.concurrent.ExecutionException;
Açıklaması şöyle
Exception thrown when attempting to retrieve the result of a task that aborted by throwing an exception. This exception can be inspected using the Throwable.getCause() method.
Örnek
Şöyle yaparız
FutureTask futureTask = new FutureTask(() -> {
  // Throw an exception to simulate an error during execution
  throw new RuntimeException("An error occurred during task execution");
});
Thread thread = new Thread(futureTask);

// Start the thread
thread.start();


try {
  // Wait for the thread to complete
  futureTask.get();
} catch (ExecutionException e) {
  System.out.println("ExecutionException");
} 
... 

11 Haziran 2023 Pazar

jshell komutu - Java 9 İle Geliyor

Giriş
Açıklaması şöyle
JShell was introduced in Java 9 and is available along with other JDK tools in the JDK_HOME/bin directory. 
...
To start with JShell, browse to the JDK_HOME/bin directory in a command-line /terminal and type jshell.
1. Sınıf tanımlanabilir
2. Metod tanımlanabilir

Startup
Açıklaması şöyle
DEFAULT: loaded if no start-up script is specified.
JAVASE: imports a lot more packages.
PRINTING: like default, but adds print convenience methods.
TOOLING : Java 21 ile geliyor. Bazı şeyler hazır geliyor. Hazır gelen komutlar şunlar
TOOLING ile bazı şeyler hazır geliyor. Hazır gelen komutlar şunlar
void jar(String... args)
void javac(String... args)args)
void javadoc(String... args)
void javap(String... args)
void jdeps(String... args)
void jlink(String... args)
void jmod(String... args)
void jpackage(String... args)
Örnek - javap
Şöyle başlatırız
jshell --start DEFAULT TOOLING
Sonra şöyle yaparız
jshell> record Point(int x, int y) { }

jshell> javap(Point.class)

Classfile /tmp/TOOLING-11410713526801554514.class
  Last modified Oct 3, 2023; size 1281 bytes
  SHA-256 checksum 6f3f6c989dacd62919ce9330c7e1cc9a9511402d044198747d9a35c66a1160f4
  Compiled from "$JShell$22.java"
public final class REPL.$JShell$22$Point extends java.lang.Record
  minor version: 0
  major version: 65
  flags: (0x0031) ACC_PUBLIC, ACC_FINAL, ACC_SUPER
  this_class: #8                          // REPL/$JShell$22$Point
  super_class: #2                         // java/lang/Record
  interfaces: 0, fields: 2, methods: 6, attributes: 5
Constant pool:
   #1 = Methodref          #2.#3          // java/lang/Record."<init>":()V
   #2 = Class              #4             // java/lang/Record
   #3 = NameAndType        #5:#6          // "<init>":()V
// ... snip ...
Komutlar
Bazıları şöyle
1. /imports
2. /help
3. / list
4. /vars
5. /methods
6. / types

6 Haziran 2023 Salı

CompletableFuture.supplyAsync metodu İle Retry

Örnek
Elimizde şöyle bir kod olsun
private CompletableFuture<String> executeApiCallWithRetry(String url) {
  CompletableFuture<String> future = new CompletableFuture<>();
  executeApiCallWithRetryImpl(url, future, 0);
  return future;
}
private void executeApiCallWithRetryImpl(String url, CompletableFuture<String> future, int retryCount) {
  if (retryCount > MAX_RETRIES) {
    future.complete("Failed after maximum retries");
    return;
  }
  CompletableFuture.supplyAsync(() -> restTemplate.getForObject(url, String.class))
    .whenComplete((result, ex) -> {
      if (ex != null) {
        try {
          Thread.sleep(RETRY_INTERVAL_MS);
        } catch (InterruptedException e) {
          Thread.currentThread().interrupt();
        }
        executeApiCallWithRetryImpl(url, future, retryCount + 1); // Recursive call
      } else {
        future.complete(result);
      }
   });
}
Şöyle yaparız
@Service
public class ApiService {
  @Autowired
  private RestTemplate restTemplate;
  private static final int MAX_RETRIES = 3;
  private static final long RETRY_INTERVAL_MS = 1000;

  public List<String> executeParallelApiCalls() {
    List<String> urls = ...;
    List<CompletableFuture<String>> futures = urls.stream()
      .map(url -> executeApiCallWithRetry(url))
      .collect(Collectors.toList()); // Wait for all operations to complete
    CompletableFuture<Void> allFutures = CompletableFuture
      .allOf(futures.toArray(new CompletableFuture[futures.size()])); // Convert result to list
    CompletableFuture<List<String>> result = allFutures.thenApply(v -> futures.stream()
      .map(future -> future.getNow("Fallback result"))
      .collect(Collectors.toList()));
    List<String> resultList = result.join();
    return resultList;
  }
}

CompletableFuture.supplyAsync metodu İle Exception Dönmek

Exception Fırlatmak
2 tane yöntem var
1 - Eğer supplyAsync() metodu içinde checked exception fırlatılıyorsa bu exception'ı yakalayıp CompletionException olarak tekrar fırlatmak gerekiyor.
2. completeExceptionally() metodu çağrılır

1. CompletionException Fırlatmak
Örnek
Şöyle yaparız
// Some code
CompletableFuture<A> future= CompletableFuture.supplyAsync(() -> {
  try {
    return someObj.someFunc(); 
  }
  catch(ServerException ex) {
    throw new CompletionException(ex);
 }
});
Daha sonra future.get() veya future.join() çağrılarında bu checked exception'a erişme imkanı var.

2. completeExcepitonally() Çağrısı Yapmak
Örnek
Şöyle yaparız.
public static CompletableFuture<Integer> converter(String convertMe) {
  CompletableFuture<Integer> future = new CompletableFuture<>();
    try {
      future.complete(Integer.parseInt(convertMe));
    } catch (Exception ex) {
      future.completeExceptionally(ex);
    }
    return future;
}
Exception Olduğunu Anlamak ve Erişmek
1. Future.join()
2. Future.get()
3. supplyAsynch + handle()
4. supplyAsynch + exceptionally()
5. supplyAsynch + whenComplete ()

Future.join() İle Checked Exception'a Erişmek
Örnek 
Şöyle yaparız. Burada belki de en güzeli sadece Exception'ı yakalamak ta olabilir. Böylece Supplier unchecked exception fırlatsa bile yakalanabilir.
CompletableFuture<A> future = ...;

A resultOfA;
try {
  resultOfA = future.join();
}
catch(CompletionException ex) {
  ...
}
Future.get() İle Checked Exception'a Erişmek
Örnek

Şöyle yaparız. Burada belki de en güzeli sadece Exception'ı yakalamak ta olabilir. Böylece Supplier unchecked exception fırlatsa bile yakalanabilir.
CompletableFuture<A> future = ...;

A resultOfA;
try {
  resultOfA = future.get();
}
catch(Exception ex) {
  ...
}
supplyAsynch metodu ve exceptionally
Burada future sonucunda exception görmek yerine exception'ı temsil eden bir sonuç döndürülür.
3 tane yöntem var.
- handle() metodu
- exceptionally() metodu
- whenComplete metodu()

handle metodu
Şöyle yaparız
CompletableFuture correctHandler = CompletableFuture.supplyAsync(() -> "A")
  .thenApply(Integer::parseInt)
  .handle((result, ex) -> {
    if (null != ex) {
      ex.printStackTrace();
      return 0;
    } else {
      System.out.println("HANDLING " + result);
      return result;
    }
  })
  .thenAcceptAsync(s -> {
    System.out.println("CORRECT: " + s);
});
exceptionally metodu
Örnek
Şöyle yaparız.
CompletableFuture parser = CompletableFuture.supplyAsync(() -> "1")
  .thenApply(Integer::parseInt)
  .exceptionally(t -> {
    t.printStackTrace();
    return 0;
  })
  .thenAcceptAsync(s -> System.out.println("CORRECT value: " + s));
whenComplete metodu
Örnek
Şöyle yaparız.
CompletableFuture correctHandler2 = CompletableFuture.supplyAsync(() -> "A")
  .thenApply(Integer::parseInt)
  .whenComplete((result, ex) -> {
    if (null != ex) {
      ex.printStackTrace();
    }
  })
  .thenAcceptAsync(s -> {
    System.out.println("When Complete: " + s);
});