4 Eylül 2023 Pazartesi

BufferedInputStream Sınıfı

Giriş
Şu satırı dahil ederiz
import java.io.BufferedInputStream;
Kalıtım şöyle
AutoCloseable
  Closeable
    InputStream
      FilterInputStream
        BufferedInputStream

read metodu
İmzası şöyle. Yani synchronized 
public synchronized int read() throws IOException

3 Eylül 2023 Pazar

List.of metodu - Unmodifiable List Döndürür

Giriş
Java 9 ile geliyor. JEP 269 ile gelen List, Set, Map arayüzlerinin of() static factory metodu.

Örnek
Şöyle yaparız.
List<String> TRAIN = List.of("...","...");
Örnek - record
Şöyle yaparız
record Employee(int id){ }

var empList = List.of(new Employee(1),
                new Employee(2),
                new Employee(3));

System.out.println(empList);

Örnek
Listede null değer olamaz.
List<Integer> list = List.of(1, 2, null); // Fails with a NullPointerException
Örnek
Listeye null eklemesi yapılamaz.
List<Integer> list = List.of(1, 2, 3);
list.contains(null); // Throws NullPointerException
Örnek
Döndürülen liste değiştirilemez.
List<Integer> list = List.of(1, 2, 3);
list.set(1, 10); // Fails
Collections.unmodifiableList Karşılaştırması
Java 8 kullanıyorsak bu metodu kullanmak gerekir.

Arrays.asList Karşılaştırması
Bu metod Arrays.asList() metodu ile karşılaştırılabilir. Arrays.asList() eski bir metod, Java 2'den beri var.  

1. Arrays.asList() array backed list döndürür. List.of() ise array backed list yerine yeni bir liste döndürür.
2. Her iki yöntemde de listeye ekleme çıkarma yapılamaz
3. Array backed list set işlemini destekler. List.of() ise desteklemez

Açıklaması şöyle. 
It takes an array or a series of elements and returns a List backed by the original array. This means any changes made to the list will directly affect the original array, and vice versa.
Dolayısıyla listeye ekleme çıkarma yapılamaz. Açıklaması şöyle. 
You can change the value of existing elements in a list but since it has a fixed size. You cannot add or remove elements from the list. Any attempt to add/remove will result in an UnsupportedOperationException.

Şöyle yaparız. Burada List.of() metodunun array backed list döndürmediği görülebilir.
Integer[] array = {1,2,3};
List<Integer> list = List.of(array);
array[1] = 10;
System.out.println(list); // Prints [1, 2, 3]
Şöyle yaparız. List.of() metodunun set işlemini desteklemediği ancak array backed list'in desteklediği görülebilir.
List<Employee> empList = List.of(new Employee(1),
                new Employee(2),
                new Employee(3));

empList.set(0, new Employee(50));// Not Supported
System.out.println(empList);


List<Employee> empList1 = Arrays.asList(new Employee(1),
                new Employee(2),
                new Employee(3));

empList1.set(0, new Employee(50));// Supported
System.out.println(empList1);

30 Ağustos 2023 Çarşamba

DatagramChannel Sınıfı - NIO Multicast Gönderme ve Alma

Örnek
Şöyle yaparız. 
1. bind : Network interface belirtilmediği için tüm ağ bağdaştırıcılarını dahil eden bir port açar. Böylece multicast olmayan paketleri de alabiliriz.
2. join : Burada loopback interface üzerindeki 224.0.0.255:9999 adresine multicast join yapılıyor. Eğer istenirse interface ismi (eth0 gibi) direkt kullanılabilir. 
// Create a DatagramChannel.
DatagramChannel channel = DatagramChannel.open();

// Bind the channel to a local port.
channel.bind(new InetSocketAddress(9999));

// Join the multicast group.
InetAddress address = InetAddress.getByName("127.0.0.1");
NetworkInterface networkInterface = NetworkInterface.getByInetAddress(address);

InetAddress group = InetAddress.getByName("224.0.0.255");
channel.join(group,networkInterface);

// Create a datagram packet.
byte[] data = "Hello, world!".getBytes();
DatagramPacket packet = new DatagramPacket(data, data.length, group, 9999);

// Send the datagram packet.
channel.send(packet);

// Close the channel.
channel.close();
Örnek
Şöyle yaparız. 
1. bind : Network interface belirtilmediği için tüm ağ bağdaştırıcılarını dahil eden bir port açar
2. join : Burada loopback interface üzerindeki 239.255.0.1:5000 adresine multicast join yapılıyor. Eğer istenirse interface ismi (eth0 gibi) direkt kullanılabilir. 
3. .setOption(StandardSocketOptions.IP_MULTICAST_IF, networkInterface); bence gerekli değil
InetAddress address = InetAddress.getByName("127.0.0.1");
NetworkInterface networkInterface = NetworkInterface.getByInetAddress(address);
InetAddress group = InetAddress.getByName("239.255.0.1")

DatagramChannel channel = DatagramChannel.open(StandardProtocolFamily.INET)
    .setOption(StandardSocketOptions.SO_REUSEADDR, true)
    .bind(new InetSocketAddress(5000))
    .setOption(StandardSocketOptions.IP_MULTICAST_IF, networkInterface);
MembershipKey key = channel.join(group, networkInterface
);

DatagramChannel Sınıfı - NIO UDP Sunucusu

constructor
Örnek
Şöyle yaparız
// Create a DatagramSocket
DatagramSocket socket = new DatagramSocket(9999);

// Receive a datagram packet
DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);
socket.receive(packet);

// Get the data from the packet
String data = new String(packet.getData(), 0, packet.getLength());

// Send a reply
String reply = "Hello, world!";
DatagramPacket replyPacket = new DatagramPacket(
  reply.getBytes(), 
  reply.length(), 
  packet.getAddress(), 
  packet.getPort());

socket.send(replyPacket);
bind metodu
Örnek
Şöyle yaparız
int port = 12345; // Change this to the desired port number
DatagramChannel channel = DatagramChannel.open(); channel.bind(new InetSocketAddress(port)); System.out.println("Server listening on port " + port); ByteBuffer buffer = ByteBuffer.allocate(1024); while (true) { buffer.clear(); InetSocketAddress clientAddress = (InetSocketAddress) channel.receive(buffer); buffer.flip(); // prepare for reading after data has been written into it System.out.println("Received message from " + clientAddress.getAddress() + ":" + clientAddress.getPort()); // Process the received data (here we're just echoing it back) channel.send(buffer, clientAddress);

29 Ağustos 2023 Salı

JavaMail IMAP

Örnek
Elimizde bir application.properties dosyası olsun
email.host=imap.example.com
email.port=993
email.protocol=imaps
email.username=your-email@example.com
email.password=your-email-password
Bir Session nesnesi yaratırız
import javax.mail.*;
import java.util.properties;

@Configuration
public class EmailConfiguration {

  @Value("${email.host}")
  private String emailHost;

  @Value("${email.port}")
  private String emailPort;

  @Value("${email.username}")
  private String emailUsername;

  @Value("${email.password}")
  private String emailPassword;

  @Bean
  public Session mailSession() {
    Properties props = new Properties();
    props.setProperty("mail.store.protocol", "imaps");
    props.setProperty("mail.imaps.host", emailHost);
    props.setProperty("mail.imaps.port", emailPort);

    // Create a new session with the properties
    Session session = Session.getInstance(props);
    session.setDebug(true); // Enable debug mode for troubleshooting

    return session;
  }
}
Sonra kendi listener nesnemizi yaratırız
@Configuration
public class EmailConfiguration {
  
  @Bean
  public EmailListener emailListener() {
    return new EmailListener(mailSession(), emailUsername, emailPassword);
  }
}
Listener şöyledir
import javax.mail.*;
import javax.mail.event.MessageCountAdapter;
import javax.mail.event.MessageCountEvent;

import com.sun.mail.imap.IMAPFolder;

public class EmailListener extends MessageCountAdapter {
  private Session session;
  private String username;
  private String password;

  public EmailListener(Session session, String username, String password) {
    this.session = session;
    this.username = username;
    this.password = password;
  }
  ...
}
startListening() metodu şöyledir
import com.sun.mail.imap.IMAPFolder;

public class EmailListener extends MessageCountAdapter {
  ...
  public void startListening() throws MessagingException, InterruptedException,
    IOException {
    Store store = session.getStore("imaps");
    store.connect(username, password);

    IMAPFolder inbox = (IMAPFolder)store.getFolder("INBOX");
    inbox.open(Folder.READ_WRITE);

    // Create a new thread to keep the connection alive
    Thread keepAliveThread = new Thread(new KeepAliveRunnable(inbox),
      "IdleConnectionKeepAlive");
    keepAliveThread.start();

    inbox.addMessageCountListener(new MessageCountAdapter() {
      @Override
      public void messagesAdded(MessageCountEvent event) {
        // Process the newly added messages
        Message[] messages = event.getMessages();
        for (Message message : messages) {
          try {
            // Implement your email processing logic here
            System.out.println("New email received: " + message.getSubject());
          } catch (MessagingException e) {
            ...
          }
        }
      }
    });

    // Start the IDLE Loop
    while (!Thread.interrupted()) {
      try {
        System.out.println("Starting IDLE");
        inbox.idle();
      } catch (MessagingException e) {
        ...
        throw new RuntimeException(e);
      }
    }
    // Interrupt and shutdown the keep-alive thread
    if (keepAliveThread.isAlive()) {
      keepAliveThread.interrupt();
    }
  }
}
KeepAliveRunnable şöyledir
import com.sun.mail.imap.IMAPFolder;
import javax.mail.MessagingException;

public class KeepAliveRunnable implements Runnable {
  private static final long KEEP_ALIVE_FREQ = 300000; // 5 minutes
  private IMAPFolder folder;
  public KeepAliveRunnable(IMAPFolder folder) {
    this.folder = folder;
  }

  @Override
  public void run() {
    while (!Thread.interrupted()) {
      try {
        Thread.sleep(KEEP_ALIVE_FREQ);

        // Perform a NOOP to keep the connection alive
        System.out.println("Performing a NOOP to keep the connection alive");
        folder.doCommand(protocol -> {
          protocol.simpleCommand("NOOP", null);
          return null;
        });
      } catch (InterruptedException e) {
        // Ignore, just aborting the thread...
      } catch (MessagingException e) {
        // Shouldn't really happen...
        System.out.println("Unexpected exception");
        e.printStackTrace();
      }
    }
  }
}
Açıklaması şöyle
We need an email server that supports the IMAP IDLE feature. IMAP IDLE allows our application to receive immediate notifications when new messages arrive in the inbox rather than relying on periodic polling.

Some servers have specific setting or timeouts that may terminate the IDLE connection after a certain period of inactivity. e.g. Gmail ~ 10 mins. So KeepAlive mechanism is necessary to receive email indefinitely.


JDBC DatabaseMetaData.getTables metodu

Giriş
Not : Bu metod çok iyi çalışmıyor. Farklı veri tabanları için farklı yöntemler kullanmak gerekir. Bir makale burada
İmzası şöyle
public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) throws SQLException
types için açıklama şöyle
Typical types are "TABLE", "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
Döndürülen sütunlar şöyle
TABLE_CAT : Catalog of the table.
TABLE_SCHEM : Catalog of the schema.
TABLE_NAME : Name of the table.
TABLE_TYPE : Type of the table. (table, view, system table, global table, alias, synonym etc..)
REMARKS : Comments on the column.
TYPE_SCHEM : Schema of the table.
TYPE_NAME : Name of the type.
SELF_REFERENCING_COL_NAME : Name of the designated column of the table.
REF_GENERATION : Either SYSTEM or, USER or, DERIVED.
Örnek - Kendi Schemam'daki Tüm Tablolar
Şöyle yaparız. Burada catalog ve schema ismi connection nesnesine göre veriliyor. Tablo ismi belirtilmiyor ama Types olarak TABLE belirtilmiş
try(ResultSet rs = conn.getMetaData().getTables(conn.getCatalog(), conn.getSchema(), null, new String[] {"TABLE"})) { ... }
Örnek - Veri tabanındaki Tüm Tablolar Yani Database Discovery
Şöyle yaparız. Burada catalog ve schema ve tablaneNamePattern parametreleri belirtilmediği için tüm schemalarındaki tüm tabloları buluyor. Tabloları buluyor çünkü Types olarak TABLE belirtilmiş
try(ResultSet rs = conn.getMetaData().getTables(null,null,null,new String[] {"TABLE"})) { while (rs.next()) { System.out.println(rs.getString("TABLE_SCHEM") + "." + rs.getString("TABLE_NAME")); } } // Output app96.t1 app96.t2 public.administration$account public.appmodule$uploadedfile public.audittrail$audittrailsuperclass

28 Ağustos 2023 Pazartesi

JEP 432 - Record patterns

Giriş
Hem instanceof, hem de switch expression kullanımında record destructure işlemine tabi tutulur. Yani içindeki değişkenlere bireysel olarak erişebiliriz

instanceof
Örnek
Elimizde şöyle bir kod olsun
record Point(int x, int y) { }
Şöyle yaparız
Object obj = new Point(2, 3);

if (obj instanceof Point(int x, int y)) {
    System.out.println("x: " + x + ", y: " + y);
} else {
    System.out.println("Not a point");
}
 switch expression
Şöyle yaparız
Object shape = new Circle(5);

String description = switch (shape) {
  case Point(int x, int y) -> "Point at (" + x + ", " + y + ")";
  case Circle(int radius) -> "Circle with radius " + radius;
  default -> "Unknown shape";
};

System.out.println(description);