31 Ekim 2023 Salı

Stream.iterate metodu

iterate metodu - seed + unary operator
İmzası şöyle. Sonsuz bir Stream yaratır. limit() ile sınırlamak gerekir
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
Açıklaması şöyle. Belirtilen seed değerinden başlar ve unary operator ile seed değeri değiştirilir.
Stream iterate(T seed, UnaryOperator<T> f) creates an infinite Stream from iterative application of a function f to an initial element seed.
Bu metod recursive (özyinelemeli veya kendi kendini çağıran) metodların veya döngülerin metodların yerine geçebilir. Bu metod sonsıuz bir Stream yarattığı için limit() ile sınırlandırmak gerekir.

Örnek
Şöyle yaparız.
DoubleStream.iterate(1.0,term -> term*2)
            .limit(n).sum();
Örnek
Şöyle yaparız.
Stream.iterate('a', i -> (char)(i + 1)).limit(26).forEach(System.out::println);
iterate metodu - seed + predicate + unary operator
İmzası şöyle. Predicate ile sınırlanan bir Stream yaratır.
public static<T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, 
  UnaryOperator<T> next)
Java 9 ile geliyor. Belirtilen seed değerinden başlar ve predicate true olduğu müddetçe unary operator ile seed değeri değiştirilir.
Örnek
Şöyle yaparız.
Stream.iterate(exception, Objects::nonNull, Throwable::getCause);
Şu kod ile aynıdır.
Stream.iterate(exception, Throwable::getCause)
      .takeWhile(Objects::nonNull)
Örnek
Belirtilen karakterlerin String içindeki indeksini bulmak için şöyle yaparız.
List<Integer> getIndexList(String word, char c) {
  return IntStream
    .iterate(word.indexOf(c),
             index -> index >= 0,//Predicate
             index -> word.indexOf(c, index + 1))
    .boxed()
    .collect(Collectors.toList());
}

26 Ekim 2023 Perşembe

Hikari API HikariPool Sınıfı

Giriş
Şu satırı dahil ederiz 
import com.zaxxer.hikari.pool.HikariPool;
Bu sınıf aslında direkt kullanılmıyor

closeConnection metodu
İmzası şöyle. Bazen buraya breakpoint koyup debug etmek gerekebiliyor
void closeConnection(final PoolEntry poolEntry, final String closureReason)


25 Ekim 2023 Çarşamba

ResultSet Stream Dönüşümü

Giriş
1. ResultSet nesnesi iterator ile sarmalanır
2. Iterator nesnesi StreamSupport kullanılarak Stream'e çevrilir.
3. Sonra şöyle yaparız
Stream<ResultSet> resultSetStream = ...
resultSetStream
  .limit(5) // Take the first 5 items
  .forEach(row -> {
    // Process the row here
});

Çevrim

Örnek
Elimizde şöyle bir kod olsun
public static void closeResource(AutoCloseable closeable) {
  if (closeable == null) {
    return;
  }
  try {
    closeable.close();
  } catch (Exception e) {
    ...
  }
}
Şöyle yaparız. Burada ResultSet kapatılıyor.  

Not : Sarmalayan iterator Java Iterator arayüzünü tam gerçekleştirmiyor. Çünkü hasNext() çağrısının yapılmasını şart hale getirmiş ama çok önemli değil çünkü SplitIterator sınıfı Iterator.hasNext() çağrısı yapmayı garanti ediyor. 
public static Stream<ResultSet> toStream(ResultSet resultSet) {
  Spliterator<ResultSet> spliterator = Spliterators.spliteratorUnknownSize(
    new Iterator<>() {
      @Override
      public boolean hasNext() {
        try {
          return resultSet.next();
        } catch (SQLException sqlException) {
          return false;
        }
      }

      @Override
      public ResultSet next() {
        return resultSet;
      }
    },
    Spliterator.IMMUTABLE | Spliterator.NONNULL | Spliterator.ORDERED
  );

  return StreamSupport.stream(spliterator, false).onClose(() -> closeResource(resultSet));
}

21 Ekim 2023 Cumartesi

Apache Benchmark Aracı - ab komutu

Giriş
JMeter yerine Apache Benchmark kullanılabilir.  Büyük miktarda trafik yaratır yani Load testing için kullanılabilir. Açıklaması şöyle
Apache benchmark is a simple-to-use tool to help you understand how an HTTP server copes with large volumes of traffic. 
...
Note that Apache Benchmark will fire off requests as fast as it possibly can, given the permitted concurrency. It’s hard to say “send 1000 requests over the space of 1 minute” — it will just do 1000 requests as fast as possible. Therefore, it’s kind of tricky to simulate a realistic load. AB is generally better for finding out at what point your service begins to degrade, and then ascertaining whether you could ever reasonably expect this load.


Windows Kurulum
https://www.youtube.com/watch?v=hUZso9TpEes adresinde Windows'a nasıl kurulacağı gösteriliyor

MacOS Kurulum
Kurmaya gerek yok, kurulu geliyor

Çıktısı
Connection times başlığı altında Total isimli satırdaki median isimli sütun iyi bir fikir verebilir.

Örnek
Şöyledir
Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.3      0       4
Processing:    19   76   2.9     76      88
Waiting:        2   55  13.4     56      87
Total:         19   76   2.9     76      88

Percentage of the requests served within a certain time (ms)
  50%     76
  66%     77
  75%     77
  80%     77
  90%     79
  95%     81
  98%     83
  99%     84
 100%     88 (longest request)

-c seçeneği
Kaç tane thread kullanılacağını belirtir. Toımcat varsayılan 200 thread ile başladığı için genellikle 200'den büyük bir değer vermek gerekir.

Örnek
Şöyle yaparız. Burada 100 tane thread kullanılıyor
ab -c 100 http://localhost:8080/
-n seçeneği
İstek sayısını belirtir.

Örnek
Şöyle yaparız
ab -n 1000 -c 1000 http://localhost:8080/thread-application/run
-r seçeneği
Açıklaması şöyle
The  -r flag means don’t exit if it gets an error. 
Örnek
Şöyle yaparız
$ ab -c 10 —n 500 —r localhost:8000/api/books
-T seçeneği
Açıklaması şöyle
By default, AB will perform a GET request so if you need to test another type of request you will have to pass it the specific option to do so and also set the content-type header of the request with the -T flag.
Örnek - POST
Şöyle yaparız. Burada -p ile event.json dosyası POST ediliyor.
$ ab -c 10 -n 500 -p event.json -r -T application/json localhost:8000/api/books




19 Ekim 2023 Perşembe

JPA @OneToMany İlişki - Bidirectional Join Tablosu Olmadan

Giriş
Eğer join tablosu olmasın istiyorsak parent tarafında OneToMany ve mappedBy, child tarafında ise ManyToOne ve JoinColumn birlikte kullanılır. Bu normal kullanım ve performanslı

Parent mappedBy="..." ile karşı sınıftaki attribute ismini belirtir. Child ise JoinColumn ile kendi tablosunda hangi sütunun foreign key olarak kullanılacağını belirtir.

Veri tabanına önce parent kaydedilir. Parent'ın PK değeri, child tabloda FK olarak kullanılır.

Bu ilişkide genellikle parent nesne silinirse child nesneler de otomatik olarak silinir. Parent'ı silip child nesneyi saklama yapılmaz. Yani genellikle şu anotasyon ile kullanılır
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
Eğer orphanRemoval = true değilse sadece parent'ı silmeye çalışırsak foreign key ile ilgili bir hata alırız.

Örnek
Şöyle yaparız. Burada orphanRemoval = true değil yani ufak bir eksiklik var.
@Entity
@Table(name = "OWNER_DETAILS")
public class Owner {
    
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "ID")
  private int id;

  @OneToMany(fetch = FetchType.LAZY, mappedBy = "owner", cascade = CascadeType.ALL)
  private List<Blog> blogList;
  ...
}

@Entity
@Table(name = "BLOG_DETAILS")
public class Blog {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "ID")
  private int id;
  
  @ManyToOne(cascade = CascadeType.ALL)
  @JoinColumn(name = "owner_id")
  private Owner owner;
  ...
}
Tablolar şöyle. Child tarafında owner_id isimli sütun görülebilir


Örnek
Şöyle yaparız. Burada orphanRemoval = true değil yani ufak bir eksiklik var.
@Entity
public class Company {
  @OneToMany(fetch = FetchType.LAZY, mappedBy = "company")
  private List<Branch> branches;
}

@Entity
public class Branch {
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "companyId")
  private Company company;
}
Örnek
Parent tarafında şöyle yaparız.
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
private List<Product> product = new ArrayList<Product>();
Child tarafında şöyle yaparız.
@ManyToOne
@JoinColumn(name = "product_Id", referencedColumnName = "product_Id", nullable = false,
  insertable = false, updatable = false)
private Order order;