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(); } }

Guice Injector Sınıfı

Giriş
Şu satırı dahil ederiz.
import com.google.inject.Injector;
createChildInjector metodu
Farklı konfigürasyonlar göre Injector yaratabilmeyi sağlar.

Örnek
Şöyle yaparız
class ForeverModule extends AbstractModule {
  ...
}

class TemporaryModule extends AbstractModule {
  ...
}

Injector foreverInjector = Guice.createInjector(new ForeverModule());

Injector injector = foreverInjector.createChildInjector(new TemporaryModule());
/*
 * Do stuff with the injector as you would normally. When you
 * get bored of that injector, create a replacement injector
 * as a child of the long-lived injector.
*/
getInstance metodu
Belirtilen Class'a ait bir nesne döner. Nesne Spring terminolojisiyle @Autowire edilmiştir.
Örnek
Şöyle yaparız
Injector injector = Guice.createInjector(new BasicModule());
Communication comms = injector.getInstance(Communication.class);

Guice Kullanımı

Maven
Şu satırı dahil ederiz
<dependency>
  <groupId>com.google.inject</groupId>
  <artifactId>guice</artifactId>
  <version>4.1.0</version>
</dependency>
Kullanım
1. Bir Injector yaratılır. Injector'ı yaratırken AbstractModule nesnesi veririz.
2. Injector.getInstance(Foo.class) çağrısı ile @Inject anotasyonları doldurulmuş bir Foo nesnesi elde ederiz
3. Eğer Enforce Explicit Binding seçili değilse, Guice JustInTimeBindings yapabilir. Yani AbstractModule tarafından bilinmeyen veya anotasyon ile işaretlenmemiş nesneleri de yaratabilir.

Örnek
Şöyle yaparız
Injector injector = Guice.createInjector(new BasicModule());
Communication comms = injector.getInstance(Communication.class);
Injector Sınıfı
Injector Sınıfı yazısına taşıdım

AbstractModule Sınıfı
AbstractModule Sınıfı yazısına taşıdım

Singleton Kullanımı
Singleton 3 farklı şekilde yapılabilir.
1. At Class level
Örnek
Şöyle yaparız
@Singleton
class SpellCheckerImpl implements SpellChecker {
   
  @Override
  public void checkSpelling() { 
    ...
  }
}

class TextEditorModule extends AbstractModule {
@Override protected void configure() { bind(SpellChecker.class).to(SpellCheckerImpl.class); } }
2. At Configuration level
Örnek
Şöyle yaparız
class TextEditorModule extends AbstractModule {
@Override protected void configure() { bind(SpellChecker.class).to(SpellCheckerImpl.class).in(Singleton.class); } }
3. At Method level
Örnek
Şöyle yaparız
class TextEditorModule extends AbstractModule {
   @Override
   protected void configure() {} 

   @Provides @Singleton
   public SpellChecker provideSpellChecker() {
      SpellChecker spellChecker = new SpellCheckerImpl();
      return spellChecker;
   }
}

27 Nisan 2021 Salı

@VisibleForTesting Anotasyonu

Giriş
Şu satırı dahil ederiz
import com.google.common.annotations.VisibleForTesting;
Açıklaması şöyle
... the annotation itself does not prevent production code from calling the annotated method
Örnek
Şöyle yaparız. Böylece testler farklı bir pakette olsa bile Bar sınıfına erişebilir
class Foo {
  ...
  @VisibleForTesting
  static class Bar {
  }
}

6 Nisan 2021 Salı

ServiceManager Sınıfı

Giriş
Şu satırı dahil ederiz
import com.google.common.util.concurrent.ServiceManager;
startAsync metodu
Örnek
Şöyle yaparız
public class ManagedGuavaServices implements Managed {
  @Inject
  private ServiceManager serviceManager;

  @Inject
  public ManagedGuavaServices(ServiceManager serviceManager) {
    this.serviceManager = serviceManager;
  }

  @Override
  public void start() throws Exception {
    serviceManager.startAsync();
    serviceManager.awaitHealthy(2, TimeUnit.SECONDS);
  }

  @Override
  public void stop() throws Exception {
    serviceManager.stopAsync();
    serviceManager.awaitStopped(2, TimeUnit.SECONDS);
 }
}

7 Mart 2021 Pazar

Traverser Sınıfı

Giriş
Şu satırı dahil ederiz.
import com.google.common.graph.Traverser;
Traverse algoritmaları olarak şunlar kullanılabilir
breadthFirst(Iterable<? extends N> startNodes)
Iterable over the nodes reachable from any of the startNodes, in the order of a breadth-first traversal
breadthFirst(N startNode)
Iterable over the nodes reachable from startNode, in the order of a breadth-first traversal
Örnek
Şöyle yaparız
Node root = new Node("root");
MutableGraph<Node> myGraph = GraphBuilder.directed().build();
Node node1=new Node(" 1 ");
Node node2=new Node(" 2 ");
Node node3=new Node(" 3 ");
Node node4=new Node(" 4 ");
Node node5=new Node(" 5 ");
myGraph.putEdge(root, node1);
myGraph.putEdge(node1, node2);
myGraph.putEdge(node1, node3);
myGraph.putEdge(node2, node4);
myGraph.putEdge(node2, node5);
//Print the nodes Depth First
Traverser.forGraph(myGraph).breadthFirst(root)
  .forEach(x->System.out.println(x));
Çıktı olarak şunu alırız
1
3 2 5 4
depthFirstPostOrder(Iterable<? extends N> startNodes)
Iterable over the nodes reachable from any of the startNodes, in the order of a depth-first post-order traversal
Örnek
Şöyle yaparız
Node root = new Node("root");
MutableGraph<Node> myGraph = GraphBuilder.directed().build();
Node node1=new Node(" 1 ");
Node node2=new Node(" 2 ");
Node node3=new Node(" 3 ");
Node node4=new Node(" 4 ");
Node node5=new Node(" 5 ");
myGraph.putEdge(root, node1);
myGraph.putEdge(node1, node2);
myGraph.putEdge(node1, node3);
myGraph.putEdge(node2, node4);
myGraph.putEdge(node2, node5);
//Print the nodes Depth First
Traverser.forGraph(myGraph).depthFirstPostOrder(root)
  .forEach(x->System.out.println(x));
root ->(1)
1 -> (2,3)
2 -> (4,5)
Çıktı olarak şunu alırız
1
3
5
4
2
depthFirstPostOrder(N startNode) metodu
Iterable over the nodes reachable from startNode, in the order of a depth-first post-order traversal
Örnek
Şöyle yaparız
Node root = new Node("root");
Graph<Node> graph = GraphBuilder.directed()
  .nodeOrder(ElementOrder.insertion())
  .<Node>immutable()
  .putEdge(root, new Node("one"))
  .putEdge(root, new Node("two"))
  .putEdge(root, new Node("three"))
  .build();

//Print the nodes in traversal order.
Traverser.forGraph(graph).depthFirstPostOrder(root)
  .forEach(x->System.out.println(x));
depthFirstPreOrder(Iterable<? extends N> startNodes)
Iterable over the nodes reachable from any of the startNodes, in the order of a depth-first pre-order traversal
forGraph(SuccessorsFunction<N> graph)
Creates a new traverser for the given general graph.
forTree(SuccessorsFunction<N> tree)
Creates a new traverser for a directed acyclic graph that has at most one path from the start node(s) to any node reachable from the start node(s), and has no paths from any start node to any other start node, such as a tree or forest