28 Nisan 2020 Salı

SpringMail JavaMailSender Arayüzü

Giriş
Açıklaması şöyle
The JavaMailSender is a class provided by Spring Boot Starter Mail and configured using a properties file.

Spring  JavaMail ile birleştirmek için şu sınıfları sunuyor.
1.MailSender Interface
2.JavaMailSender Interface
3.JavaMailSenderImpl Class
4.SimpleMailMessage Class
5.MimeMessagePreparator Interface
6.MimeMessageHelper Class

Bu arayüz org.springframework.mail.MailSender arayüzünden kalıtır. Açıklaması şöyle.
It is sub-interface of MailSender. It supports MIME messages and is used with MimeMessageHelper class. It is used for creating JavaMail MimeMessage. MimeMessagePreparator mechanism is recommended for the use of this interface.
Bu sınıfın host,username,password,javaMailProperties alanları doldurulur daha sonra send() metodu çağrılır.

Örnek
Bazı kodlarda şöyle yapılıyor ancak MailSender arayüzünden kalıtan başka arayüz olmadığı için direkt JavaMailSender arayüzü de kullanılabilir.
public class FooImpl implements Foo {
  private MailSender mailSender;
  ...
}
Şöyle yaparız.
@Service
public class EmailService {

  @Autowired
  private JavaMailSender mailSender;
  ...
}
createMimeMessage metodu
Şöyle yaparız.
MimeMessage message = mailSender.createMimeMessage();
send metodu - MimeMessage
javax.mail.internet.MimeMessage nesnesi gönderir.

Örnek - Sadece Metin
Şöyle yaparız.  Spring javax.mail.internet.MimeMessage sınıfından kalıtan org.springframework.mail.SimpleMailMessage sınıfını sağlar. Bu sınıf ile eklenti gönderilemez.
SimpleMailMessage mailMessage = new SimpleMailMessage();
mailMessage.setFrom("some mail");
mailMessage.setSubject(title);
mailMessage.setText(body);
String to = ...;
mailMessage.setTo(to);
mailSender.send(mailMessage);
Örnek
Daha karmaşık (örneğin eklenti içeren) mesajlar göndermek için MimeMessageHelper kullanılabilir. Şöyle yaparız.
MimeMessage message = sender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message);

helper.setText("Test body");
helper.setSubject("Test subject");
helper.setTo("mail@gmail.com");
sender.send(message);
send metodu - MimeMessagePreparator
org.springframework.mail.javamail.MimeMessagePreparator callback olarak kullanılan bir arayüz.

Örnek
Şöyle yaparız.
MimeMessagePreparator messagePreparator = ...;
mailSender.send(messagePreparator);

27 Nisan 2020 Pazartesi

SpringBoot @ConfigurationProperties Anotasyonu - Properties Dosyası Okuma

Giriş
Şu satırı dahil ederiz.
import org.springframework.boot.context.properties.ConfigurationProperties;
@EnableConfigurationProperties İle İlgisi
Bu anotasyonun çalışması için eski SpringBoot ile @EnableConfigurationProperties tanımlı olmalıydı çünkü Spring class path scanning yaparken bu anotasyonu tanımıyordu. Yeni SpringBoot için açıklama şöyle. Yani artık @EnableConfigurationProperties anotasyonunu kullanmaya gerek yok.
As, of Spring Boot 2.2, Spring finds and registers @ConfigurationProperties classes via classpath scanning. Therefore, there is no need to annotate such classes with @Component (and other meta-annotations like @Configuration) or even use the @EnableConfigurationProperties
@PropertySource İle İlgisi
Bu anotasyon normalde application.properties dosyasını okur. Eğer okunacak dosyayı belirtmek istersek @PropertySource kullanılabilir. Test yazıyorsak @TestPropertySource kullanılabilir.

@ConstructorBinding İle İlgisi
Bu anotasyon normalde kendi içindeki field'ları direkt doldurur. Eğer nesnemizin constructor metodunu kullanarak doldurmak istersek, bu anotasyonla birlikte @ConstructorBinding kullanılır

POJO okuma örneklerini @ConfigurationProperties Anotasyonu POJO Okuma yazısına taşıdım.

Neden Lazım
Açıklaması şöyle.
Using the @Value("${property}") annotation to inject configuration properties can sometimes be cumbersome, especially if you are working with multiple properties or your data is hierarchical in nature. Spring Boot provides an alternative method of working with properties that lets strongly typed beans govern and validate the configuration of your application
- Bu anotasyonu kullanırsak her alanı @Value olarak işaretlemeye gerek kalmaz.
- Bu anotasyon ile işaretli sınıfın içinde başka bean'ler varsa @Configuration olarak ta işaretlenir.

locations Alanı
Bu alan artık yok. Eskiden şöyleydi.
@EnableConfigurationProperties
@SpringBootApplication
@ConfigurationProperties(locations = {"wtf.yml"}) //classpath:wtf.yml
public class SomeApp {
  
  public static void main(final String[] args) {
    SpringApplication.run(SomeApp.class, args);
  }
  

  @Value("${readTimeout}")
  public int readTimeout;
}
prefix Alanı
Üye alan ismiyle application.properties içindeki alan aynı olmalı.

Örnek - Basit string okuma
Elimizde şöyle bir kod olsun.
@ConfigurationProperties(prefix = "server")
public class ApplicationConfiguration {

  private String port;

  public String getPort() {
    return port;
  }

  public void setPort(String port) {
    this.port = port;
  }
}
application.properties şöyle olsun.
server.port = 8085
Şöyle yaparız.
@Controller
public class TestController {

  @Autowired
  ApplicationConfiguration applicationConfiguration;
  ...
}
Örnek - Basit string okuma
Şöyle yaparız.
@Configuration
@ConfigurationProperties(prefix = "animal")
public class Animal {
  private Cat cat;

 
  public Cat getCat() {
    return cat;
  }

  public static class Cat {

    @Value("${leg}")
    private String leg;

    public String getLeg() {
      return leg;
    }
  } 
}
Örnek - Map Okuma
application.properties şöyle olsun
movies.names.M1001=SpiderMan
movies.names.M1002=Thor
movies.names.M1003=Logan
movies.names.M1004=Conjuring2
movies.names.M1005=StarWars
Şöyle yaparız.
@EnableConfigurationProperties
@PropertySource(value ="application.properties")
@ConfigurationProperties(prefix="movies")
public class MovieCollections {

  private Map<String, String> names;
  ...
}
value Alanı
prefix ile aynıdır

Örnek
Şöyle yaparız.
@ConfigurationProperties("threadPools")
internal class ThreadPoolsProperties {
  ...
}