15 Ağustos 2023 Salı

Google HTTP Client Library

Maven
Şu satırı dahil ederiz
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.google.http-client</groupId>
      <artifactId>google-http-client-bom</artifactId>
      <version>1.43.3</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>


8 Haziran 2023 Perşembe

Caffeine Cache Arayüzü

Giriş
Şu satırı dahil ederiz
import com.github.benmanes.caffeine.cache.Cache;
put metodu
Örnek
Şöyle yaparız
Cache<String, String> cache = Caffeine.newBuilder().build();
cache.put("key", "value");
cache.getIfPresent("key");
stats metodu
Örnek
Şöyle yaparız
Cache<String, String> cache = Caffeine.newBuilder()
        .recordStats() // Enabled statistics collection
        .build();

// Add to the cache
cache.put("1", "value_1");
cache.put("2", "value_2");

// Simulate hit and miss from cache
cache.getIfPresent("1");
cache.getIfPresent("3");

System.out.println(cache.stats());
Çıktı şöyle
"CacheStats"{
   hitCount=1,
   missCount=1,
   loadSuccessCount=0,
   loadFailureCount=0,
   totalLoadTime=0,
   evictionCount=0,
   evictionWeight=0
}



Caffeine Kullanımı

Maven
Şu satırı dahil ederiz
<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>3.1.6</version>
</dependency>
Caffeine.newBuilder() çağrısı yaparak bir Cache  veya LoadingCache nesnesi yaratırız

Caffeine'in hızlı olmasının sebebi şöyle.
The main difference is because Caffeine uses ring buffers to record & replay events, whereas Guava uses ConcurrentLinkedQueue. The intent was always to migrate Guava over and it made sense to start simpler, but unfortunately there was never interest in accepting those changes. The ring buffer approach avoids allocation, is bounded (lossy), and cheaper to operate against.
Thread
Açıklaması şöyle.
Caffeine, like Guava, does not create threads so it cannot schedule work outside of user activity.
Caffeine AsyncCache Arayüzü CompletableFuture nesnesi döner. Bu arayüz ise gerçek nesne döner.

Scheduler
Açıklaması şöyle.
Guava performs expiration on calling threads, so nothing occurs until the next access. You could use Caffeine with a configured scheduler which will perform the work on a background thread.


6 Ekim 2022 Perşembe

ClassPath Sınıfı

Giriş
Şu satırı dahil ederiz
import com.google.common.reflect.ClassPath;
from metodu
Metaspace bilgisini verir

Örnek
Şöyle yaparız
ClassPath classPath = ClassPath.from(BuggyAppLoader.class.getClassLoader()); 
Set<ClassInfo> classes = classPath.getAllClasses(); 
for(ClassInfo classInfo : classes) {     
     logger.info(classInfo.getName()); 
}


27 Temmuz 2022 Çarşamba

Guice JustInTimeBindings

Giriş
Soru şöyle. Yani Guice bazı nesneleri kendisi otomatik yaratabiliyor. Bu açıdan Jakarta EE ile benzeşiyor.
Q : How does Guice inject classes without an @Inject-annotated constructor?
A : Guice bindings that are not declared in modules are known as Just-in-time Bindings, and by default Guice is willing to call constructors that take zero arguments:
...
If you haven't required explicit bindings and you have a public no-arg constructor, Guice will call it as if you had marked it with @Inject. This is in contrast to Dagger, which will only call @Inject-annotated constructors:
Enforce Explicit Bindings şöyle yapılır
class ExplicitBindingModule extends AbstractModule {
  @Override
  protected void configure() {
    binder().requireExplicitBindings();
  }
}
Örnek
Elimizde şöyle bir kod olsun. Eğer "Enforce Explicit Bindings" yoksa ve DepB no-arg constructor'a sahipse, Guice DepB nesnesini kendiliğinden yaratabilir.
public class ServiceClass {
  @Inject
  public ServiceClass(DepA depA, DepB depB) {
    ...
  }
}

@Provides
public DepA provideDepA() {
 //constructs DepA object and returns it
}



22 Ekim 2021 Cuma

Guice Multibinder Sınıfı

Giriş
Şu satırı dahil ederiz
import com.google.inject.multibindings.Multibinder;
Aynı arayüzü gerçekleştiren tüm sınıfları Set olarak alabilmemizi sağlar. List olarak @Inject edemeyiz.

Benzer yetenek Spring ile de geliyor. Ancak farklı olarak aynı arayüzü gerçekleştiren bean'leri List veya Set olarak alabiliriz.

Örnek
Şöyle yaparız. Böylece Action sınıfından kalıtan her şeyi alabiliriz.
Multibinder<Action> actionBinder = Multibinder.newSetBinder(binder(), Action.class);
actionBinder.addBinding().to(FooAction.class);
actionBinder.addBinding().to(BarAction.class);
Şöyle yaparız
@Inject
public Foo(Set<Action> actions) {
  ...
}
Örnek
Şöyle yaparız. Böylece elimizde soyut bir Module olur
public abstract class ActionModule extends AbstractModule {
  private Multibinder<Action> actionBinder;

  @Override
  protected void configure() {
    actionBinder = Multibinder.newSetBinder(binder(), Action.class);
    configureActions();
  }

  //Override this method to call {@link #bindAction}.
  protected abstract void configureActions();

  protected final LinkedBindingBuilder<Action> bindAction() {
    return actionBinder.addBinding();
  }
}
Module gerçekleştirimi için şöyle yaparız.
public final class MyStandardActionModule extends ActionModule {
  @Override
  protected void configureActions() {
    bindAction().to(FooAction.class);
    bindAction().to(BarAction.class);
    // If you need to instantiate an action through a Provider, do this.
    bindAction().toProvider(BazActionProvider.class);
    // You can also scope stuff:
    bindAction().to(MySingletonAction.class).in(Singleton.class);
  }
}



11 Ekim 2021 Pazartesi

Guice AbstractModule Sınıfı

Giriş
Şu satırı dahil ederiz.
import com.google.inject.AbstractModule;
Metodların karşılığı şöyle
Guice DSL syntax         Mental model
bind(key).toInstance(value) map.put(key, () -> value) (instance binding)
bind(key).toProvider(provider) map.put(key, provider)    (provider binding)
bind(key).to(anotherKey) map.put(key, map.get(anotherKey)) (linked binding)
@Provides Foo provideFoo() {...} map.put(Key.get(Foo.class), module::provideFoo) (provider                                                            (method binding)
bind metodu
Örnek - to 
Şöyle yaparız. Burada her seferinde yeni bir DefaultCommunicatorImpl yaratılır
public class BasicModule extends AbstractModule {

  @Override
  protected void configure() {
    bind(Communicator.class).to(DefaultCommunicatorImpl.class);
  }
}
Örnek - toInstance 
Şöyle yaparız. Burada her seferinde aynı DefaultCommunicatorImpl kullanılır
public class BasicModule extends AbstractModule {
DefaultCommunicatorImpl communicator = ...;
@Override protected void configure() { bind(Communicator.class).to(communicator);
} }
Örnek - toInstance 
Şöyle yaparız. Burada her seferinde yeni bir Communication yaratılır
public class BasicModule extends AbstractModule {
@Override protected void configure() {
bind(Communication.class).toInstance(new Communication(true)); } }
Örnek - toConstructor 
Şöyle yaparız. Burada her seferinde yeni bir Communication yaratılır ve Boolean alan constructor'ı kullanılır.
public class BasicModule extends AbstractModule {
@Override protected void configure() { bind(Boolean.class).toInstance(true); bind(Communication.class).toConstructor( Communication.class.getConstructor(Boolean.TYPE)); } }
install metodu
Ortak olan şeylerin bir AbstractModule altında toplanabilmesini sağlar.
Örnek
Şöyle yaparız
class TextEditorModule extends AbstractModule {
@Override protected void configure() { install (new MyCommonModule(); } }