Awesome John

Yanlış hatırlamıyorsam ya 2010 ya da 2011 yılındaydı. O seneler rahatsızlığım yüzünden çok sık Türkiye’ye gidip gelmem gerekti.

Yine o sıkıntılı yolculukların birinde, İstanbul’da anadolu yakasındaki bir alışveriş merkezinde zaman öldürmek zorunda kaldığımızda gördüm onu.

Masadan kalktım ve çay siparişi vermek için fast foodculardan birine doğru yanaştım. Üzerimde eşimin New York’taki NBA mağazasından aldığı ama sadece çok dikkatli bakan birinin New York yazısını görebileceği çok basit bir t-shirt vardı.

Tam siparişi verecekken önümdeki kolsuz bir t-shirt giymiş iri kıyım adam bana doğru döndü. Bana o herkesten farklı Türkçesiyle “orası benim köyüm” dedi. Karşımda efsane Asım Can Gündüz vardı. Ben tabii ki onu hemen tanıdım.

Normalde en olmadık durumlarda cevabı yapıştırırım ama o an onu orda görmenin şaşkınlığıyla ne dediğini anlamaya çalışarak  suratına salak salak baktım herhalde ki bana tekrar “Orası benim köyüm” dedi. İkinci kere söyleyince New York’tan bahsettiğini bu sefer anladım ve ona şu korkunç cevabı verdim. “Hiç köy olur mu baba”.

Anında toparlamaya çalışıp daha da saçmalayarak “Asım Can Gündüz efsane var mı yeni bir şeyler?” diye sordum. Delikanlının hası olduğunu kanıtlayan kibarlıkla “Yeni projeler var tvde yeni bir şeyle yapacağım” dedi. Birinin onu tanıması ve ilgi göstermesi sanki hoşuna gitti.

Çaylar elimde masaya dönerken – kafamda yalnız ve güzel ülkem sen ne acayip bir yersin, senin gibi bir efsane daha farklı bir şeyler yapıyor mu olmalıydı, bu olanlar gerçek miydi lan, vs vs gibi saçma sapan bir sürü düşünce tam da ne düşündüğümü  bilemeden dönerken – yanımdaki Sarp’ın “Kimdi lan bu? Adını bir türlü hatırlayamadım” diyen sesiyle dünyaya geri ışınlandım.

Bugün internet sitelerinde ölüm haberini görünce tekrar yad etmek istedim delikanlı efsane abimizi.

Guice Throwing Providers

In my current project we are using guice for managing dependencies. Guice is very easy to start with and you can integrate it into your project with minimum effort.

Guice comes with standard extensions. At one point I had to take a look at the throwing providers extension. The reason is according to the documentation guice isn’t very good at handling exceptions that occur during provision. During startup when guice wires up dependencies if you need to do some I/O operations (loading property files for example) it is better to use throwing providers.

So far so good. The problem about throwing providers is that the documentation found here is really confusing. Code for some of the classes (FeedFactory) mentioned in the documentation is not provided.

Another confusing point is that according to the documentation @CheckedProvides has all the benefits of @Provides methods, and also allows you to specify exceptions. However there is a fundamental difference between @Provides and @CheckProvides. When you annotate a method with @Provides the type of the object you want to inject is the same as the method return type. On the other hand when you use @CheckedProvides you can inject the provider not the object that the provider provides.

Let me try to give an example.

Let’s say that I have a Foo class with a dependency on Bar class:

package com.example;

public class Foo {
    private final Bar bar;
    public Foo(Bar provider){
        this.bar = provider;
    }
    public Bar getBar() {
        return bar;
    }
}

 

package com.example;

public class Bar {
    private String id;
    public Bar() {
        this.id = "Default id";
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getId() {
        return id;
    }
}

In order to inject Bar dependency I use the @Inject annotation on Foo constructor. So Foo becomes:

package com.example;

import com.google.inject.Inject;

public class Foo {
    private final Bar bar;
    @Inject
    public Foo(Bar bar){
        this.bar = bar;
    }
    public Bar getBar() {
        return bar;
    }
}

Let’s assume that I would like to create a Bar instance myself and inject it into Foo and creating a Bar instance might throw the following exception.

package com.example;

public class AppException extends Exception{

    public AppException(String message) {
        super(message);
    }
}

In this case I need to create a throwing provider.

The first step to create a throwing provider is to extend CheckedProvider interface:

package com.example;

import com.google.inject.throwingproviders.CheckedProvider;

public interface BarProvider<T> extends CheckedProvider<T> {
    T get() throws AppException;
}

After creating the interface that extends CheckedProvider you have to install ThrowingProviderBinder in your module and annotate a method with @CheckedProvides:

package com.example;

import com.google.inject.AbstractModule;
import com.google.inject.throwingproviders.CheckedProvides;
import com.google.inject.throwingproviders.ThrowingProviderBinder;

public class AppModule extends AbstractModule {
    protected void configure() {
        install(ThrowingProviderBinder.forModule(this));
    }
    @CheckedProvides(BarProvider.class)
    Bar getInner() throws AppException {
        Bar bar = new Bar();
        bar.setId("A different id");
        return bar;
    }
}

Documentation says @CheckedProvides has all the benefit of @Provides so the above steps should be enough in order to inject Bar instance that we created with a different id into Foo. Let’s try:

package com.example;

import com.google.inject.Guice;
import com.google.inject.Injector;

public class App {
    public static void main(String[] args) {
        Injector in = Guice.createInjector(new AppModule());
        Foo foo = in.getInstance(Foo.class);
        System.out.println(foo.getBar().getId());
    }
}

When you run the above example the result is the following:

Default id

So what happened? Guice did not call our getInner method annotated with @CheckedProvides. Instead it created the default instance of Bar class with Default id.

The reason is that methods annotated with @CheckedProvides works quite differently than methods annotated with @Provides.

@CheckedProvides creates a dynamic implementation of the interface given as the value. (BarProvider.class in our case) As a result you cannot inject Bar directly but can inject a BarProvider.

Let’s modify our Foo class:

package com.example;

import com.google.inject.Inject;

public class Foo {
    private final Bar bar;

    @Inject
    public Foo(BarProvider<Bar> provider) throws AppException {
        this.bar = provider.get();
    }
    public Bar getBar() {
        return bar;
    }
}

Let’s run our application again.

A different id

And now we see the expected result.

But wait a minute. Is this really an elegant solution to deal with exceptions. I don’t think so.

First and most important of all, Foo class now needs to know about BarProvider. This makes my model dependent on Guice.

Second point is that for each exception that you would like to handle you need to repeat the steps above. Boilerplate code is bigger than the initialization logic itself.