30 Ocak 2022 Pazar

Jakarta EE JPA

Giriş
Şeklen şöyle. Şu anda JPA 3.1 son sürüm.

Maven
Örnek - Eski
Şu satırı dahil ederiz
<dependency>
  <groupId>javax.persistence</groupId>
  <artifactId>javax.persistence-api</artifactId>
  <version>${javax.persistence.version}</version>
</dependency>
Örnek
Şu satırı dahil ederiz
<dependency>
<groupId>jakarta.persistence</groupId> <artifactId>jakarta.persistence-api</artifactId> <version>3.1.0</version> // latest version </dependency>
Örnek - Hibernate
Şu satırı dahil ederiz. Burada JPA sağlayıcısı olarak Hibernate kullanılıyor
<dependency>
  <groupId>jakarta.persistence</groupId>
  <artifactId>jakarta.persistence-api</artifactId>
  <version>3.0.0</version>
</dependency>
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-core-jakarta</artifactId>
  <version>5.6.4.Final</version>
</dependency>
<dependency>
  <groupId>org.glassfish.jaxb</groupId>
  <artifactId>jaxb-runtime</artifactId>
  <version>3.0.0</version>
</dependency>

20 Ocak 2022 Perşembe

JAX-RS @ApplicationPath Anotasyonu - web.xml yerine geçer

Giriş
Şu satırı dahil ederiz
import jakarta.ws.rs.ApplicationPath;
Örnek
Şöyle yaparız. /api/* isteklerini karşılayan bir servlet başlatır
import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application; @ApplicationPath("api") public class JerseyConfigs extends Application { } // Access as /api/hello import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; @Path("hello") public class HelloController { @GET public String getHello() { return "Hello, JAX-RS !!!"; } }
Açıklaması şöyle
By simply extending the Application class from JAX-RS, and adding the @ApplicationPath annotation, now you’ve configured Jersey.

Through the annotation you can define the url pattern, and other Jersey configurations can be added by overriding methods in the Application class.

Note we didn’t specify packages to scan, what will happen is that jersey will scan all our application classes for JAX-RS annotated classes.
Örnek
Şöyle yaparız/api/* isteklerini karşılayan bir servlet başlatır
import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application;

@ApplicationPath("api")
public class BaseApplication extends Application {

}

Jakarta Kullanımı

Neden Paket İsimleri Değişti?
Açıklaması şöyle. Eclipse Foundation teknolojyi Jakarta EE olarak yeniden markalaştırdı ama kod paketlerinin değişmesinin ana sebebi Oracle'ın javax paket ismini kullandırmak istememesi.
After Oracle turned the Java EE specs over to the Eclipse Foundation, they have since rebranded it as Jakarta EE. This includes servlets, JMS, JPA, and many others. What was once Java Messaging Service is now Jakarta Messaging Service.

And Jakarta EE 9 is the version where all these specs changes their package prefix from javax to jakarta. (Oracle wouldn’t grant Eclipse the javax prefix nor give them any sort of license).
Paket İsimlerini Değiştirmek
Eclipse Transformer kullanarak şöyle yaparız
java -jar org.eclipse.transformer.cli-0.4.0-SNAPSHOT-all.jar \ -i input_directory \ -o output_directory \ -x jakarta-renames.properties \ -t jakarta-direct.properties
1. Jakarta EE 8
Eclipse Foundation tarafından verilen ilk sürüm. Bu sürüm için iki tane dependency var. 

Birinci Kullanım
Açıklaması şöyle. Yani sadece bağımlılığı değiştirmek yeterli. Kodda paket isimler değişmiyor.
Jakarta EE8 was the first release after the Eclipse foundation overtook the project from Oracle. Nothing but the name has changed. Your existing Java EE8 projects will work out of the box. In your Maven dependencies, you can now use the new Jakarta EE8 platform reference.
Maven
Jakarta EE 8 için şu satırı dahil ederiz
<dependency>
<groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>8.0.1</version> <scope>provided</scope> </dependency>
Gradle
Şu satırı dahil ederiz
compileOnly 'javax:javaee-api:8.0.1'
İkinci Kullanım
Bu yeni bağımlılık ile kod içindeki paket isimleri artık javax.* yerine jakarta.* haline geliyor. Şöyle yaparız
<dependency>
<groupId>jakarta.platform</groupId> <artifactId>jakarta.jakartaee-api</artifactId> <version>8.0.0</version> <scope>provided</scope> </dependency>
2. Jakarta EE 9
Açıklaması şöyle. Yani kodda sadece namespace değişikliği gerekiyor
The goal of Jakarta EE 9 was the namespace change from javax.* to jakarta.*.
...
... Jakarta EE9 brings no special changes. Since the namespace change behind the scenes is very complex, this release was necessary for platform and library developers.  
Açıklaması şöyle. Benzer bir açıklama burada
By the way, most of the application servers will do the namespace migration for you during deployment. So as an application developer you can still use the javax.* namespaces, even if your target runtime will be Jakarta EE9. This means your ‘old’ application using the javax.* namespace will be running fine on newer Jakarta EE severs. 
Yani elimizde şöyle eski bir kod olsun. Bu kod sorunsuz çalışır
/* Jakarta EE8 */
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("api")
public class BaseApplication extends Application {

}
Yani elimizde şöyle yeni bir kod olsun. Bu kod sorunsuz da çalışır
/* Jakarta EE9 */
import jakarta.ws.rs.ApplicationPath; import jakarta.ws.rs.core.Application; @ApplicationPath("api") public class BaseApplication extends Application { }
Eski kodlar Wildfly 26'ya kadar sorunsuz çalışacak. Açıklaması şöyle. Daha sonra her şeyin tamamen yeni isim alanına geçmesi gerekiyor. 
Applications using the jakarta.* namespace will only work on fully compatible Jakarta EE9 servers (e.g., wildfly-preview-26.0.0). Most of the official Jakarta EE servers are still on Jakarta EE 8. So from the perspective of an application developer, it currently makes no sense to switch to the new namespace. 

3. Jakarta EE 9.1
Açıklaması şöyle. Java 11 desteği geliyor
The Jakarta EE9.1 project is similar to Jakarta EE9 just an intermediate release. The difference between Jakarta EE 9 and 9.1 is the JDK 11 support.
Maven
Şu satırı dahil ederiz
<dependency>
  <groupId>jakarta.platform</groupId>
  <artifactId>jakarta.jakartaee-api</artifactId>
  <version>9.1.0</version>
  <scope>provided</scope>
</dependency>
Gradle
Şu satırı dahil ederiz
dependencies { providedCompile 'jakarta.platform:jakarta.jakartaee-api:9.1.0' }
4. Jakarta EE 10
Açıklaması şöyle
Jakarta Servlet (6.0)
Jakarta Server Pages (3.1)
Jakarta Expression Language (5.0)
Jakarta WebSocket (2.1)
Jakarta Authentication (3.0)
JAX-RS 3.1

Jakarta EE @Decorator Anotasyonu

Örnek
Şöyle yaparız
import javax.annotation.Priority;
import javax.decorator.Decorator;
import javax.decorator.Delegate;
import javax.enterprise.inject.Any;
import javax.inject.Inject;
import javax.interceptor.Interceptor;

@Decorator
@Priority(Interceptor.Priority.APPLICATION)
public class Manager implements Worker {

  @Inject
  @Delegate
  @Any
  private Worker worker;

  @Override
  public String work(String job) {
    return "will delegate to a programmer -> " + worker.work(job);
  }
}


Jakarta EE @Produces Anotasyonu - Bean Tanımlar

Giriş
Açıklaması şöyle
Even though the @Produces annotation is used for defining injectable beans, methods with this annotation also benefit from dependency injection
Örnek
Şöyle yaparız
@Produces
MyBean mb(InjectMe injectMe) { 
  // "injectMe" is injected and can be used for constructing "MyBean"
  return new MyBean(injectMe);
}
Örnek
Şöyle yaparız
public interface Connection extends AutoCloseable {

  void commit(String execute);
}

@ApplicationScoped
class ConnectionProducer {


  @Produces
  Connection getConnection() {
    return new SimpleConnection();
  }

  public void dispose(@Disposes Connection connection) throws Exception {
    connection.close();
  }
}

Jakarta EE @Qualifier Anotasyonu

Giriş
Açıklaması şöyle. Yani seçilebilecek iki bean arasından hangisini istediğimizi belirtiriz.
The @Qualifier annotation can be applied to another annotation for creating a custom qualifier:
...
In contrast to Spring’s @Qualifier, the Jakarta EE @Qualifier does not possess a String value attribute and hence, cannot be applied directly to bean definitions. Custom qualifiers can be further refined with additional attributes. An example for such additional attributes is the built-in @Named qualifier, which can be used both in Spring and Jakarta EE.
Açıklaması şöyle
If we don't have @Qualifier set, CDI won't know the default implementation and will throw the AmbiguousResolutionException. You can solve this problem using the Named annotation or a Qualifier. In our case, we will use the Qualifiers.
Örnek - Custom Qualifier
Şöyle yaparız
// custom qualifier definition:

@Qualifier
@Retention(RUNTIME)
@Target({ TYPE, METHOD, FIELD, PARAMETER })
public @interface Feline { }

// bean definition:

@Feline
class Cat implements Pet { }

// injection point:

@Inject
@Feline
Pet felinePet;
Örnek - Custom Qualifier
Elimizde şöyle bir kod olsun
public interface Instrument {
String sound(); } public enum InstrumentType { STRING, PERCUSSION, KEYBOARD; } @Qualifier @Retention(RUNTIME) @Target({TYPE, METHOD, FIELD, PARAMETER}) public @interface MusicalInstrument { InstrumentType value(); }
Farklı sınıfları tanımlayan şöyle bir kod olsun
@MusicalInstrument(InstrumentType.KEYBOARD)
@Default
class Piano implements Instrument {
  ...
}

@MusicalInstrument(InstrumentType.STRING)
class Violin implements Instrument {
...
}

@MusicalInstrument(InstrumentType.PERCUSSION)
class Xylophone implements Instrument {
  ...
}
Şöyle yaparız
@ApplicationScoped
public class Orchestra {

  @Inject
  @MusicalInstrument(InstrumentType.PERCUSSION)
  private Instrument percussion;
  @Inject
  @MusicalInstrument(InstrumentType.KEYBOARD)
  private Instrument keyboard;

  @Inject
  @MusicalInstrument(InstrumentType.STRING)
  private Instrument string;

  @Inject
  private Instrument solo;

  @Inject
  @Any
  private Instance<Instrument> instruments;

}
Default Qualifier
Açıklaması şöyle
In the absence of a qualifier, the built-in @Default qualifier is assumed both for bean definition and injection point. So the following, simple example without explicit qualifiers

// bean definition without explicit qualifier:

class Cat implements Pet { }

// injection point without explicit qualifier

@Inject
Pet felinePet;

is equivalent to the following example with an explicit @Default qualifier:
// bean definition with @Default made explicit:

@Default
class Cat implements Pet { }

// injection point with @Default made explicit:

@Inject
@Default
Pet felinePet;






Jakarta EE SeContainer Arayüzü

Giriş
Şu satırı dahil ederiz
import javax.enterprise.inject.se.SeContainer;
import javax.enterprise.inject.se.SeContainerInitializer;

Örnek
Şöyle yaparız
try (SeContainer container = SeContainerInitializer.newInstance().initialize()) {
    Vehicle vehicle = container.select(Vehicle.class).get();
    vehicle.move();

    Car car = container.select(Car.class).get();
    car.move();

    System.out.println("Is the same vehicle? " + car.equals(vehicle));
}

public interface Vehicle {

    void move();
}

@ApplicationScoped
public class Car implements Vehicle {
//... implementation here
}

Jakarta EE @ApplicationScoped Anotasyonu

Giriş
Eski kodlarda şu satırı dahil ederiz.
import javax.ejb.ApplicationScoped;
Şu satırı dahil ederiz
import jakarta.enterprise.context.ApplicationScoped;
Normalde Jakarta EE CDI ile herhangi bir anotasyon kullanmaya gerek yok. Açıklaması şöyle
The requirements for a CDI bean are very minimal: a default constructor, implicitly or explicitly defined, and a concrete class is all that is needed. There is no need to use any kind of annotation, to indicate it can be handled through the CDI subsystem.
Ancak bazen CDI bean'lerine kapsam (scope) vermek gerekir. Çünkü bunu yapmazsak, CDI bean her seferinden yeniden yaratılır. Açıklaması şöyle
Most of the time, an annotation is placed on the class to indicate when the bean can be disposed of, and how many copies of the bean can be created. In the absence of such an annotation, the bean is created every time an 'Injection' is requested and disposed of when the other class is disposed of.
Verilebilecek kapsam anotasyonları 3 tane. Açıklaması şöyle
@jakarta.enterprise.context.ApplicationScoped: one instance for the entire application.

@jakarta.enterprise.context.SessionScoped: an instance is typically linked with a user Session like the HTTP Session.

@jakarta.enterprise.context.RequestScoped: an instance for each user request.

Since the ApplicationScoped can't hold any user or request specific information, it is ideal for providing functionality to your application, also known as services.

SessionScoped is typical for holding user information (like logged in user) and RequestScoped can be used to keep information related to the specific user request. 
@Application anotasyonu state tutmayan singleton bir bean yaratır. Açıklaması şöyle
Since the ApplicationScoped can't hold any user or request specific information, it is ideal for providing functionality to your application, also known as services.

SessionScoped is typical for holding user information (like logged in user) and RequestScoped can be used to keep information related to the specific user request. 
Örnek
Şöyle yaparız
@ApplicationScoped
public class GreetingService {
...
}

13 Ocak 2022 Perşembe

Jakarta EE InitialContext Sınıfı - JNDI Erişimi İçindir

Giriş
Şu satırı dahil ederiz
import javax.naming.Context;
import javax.naming.InitialContext;
Açıklaması şöyle
Java Naming and Directory Interface (JNDI) is a Java API that allows clients to discover and look up data and objects via a name. These objects can be stored in different naming or directory services, such as Remote Method Invocation (RMI), Common Object Request Broker Architecture (CORBA), Lightweight Directory Access Protocol (LDAP), or Domain Name Service (DNS).

In other words, JNDI is a simple Java API (such as 'InitialContext.lookup(String name)') that takes just one string parameter, ...
constructor
Şöyle yaparız.
Context ctx = new InitialContext();
createSubcontext metodu
Şöyle yaparız.
Context ic = new InitialContext();

ic.createSubcontext("java:");
ic.createSubcontext("java:comp");
ic.createSubcontext("java:comp/env");
ic.createSubcontext("java:comp/env/jdbc");
ic.createSubcontext("java:comp/env/jdbc/multiDS");
lookup metodu
Açıklaması şöyle.
When you get the datasource through a JNDI lookup it is a shared resource configured in your container. And it's that container's job to manage the lifecycle of the datasource.
Object döndüğü için istenilen tipe cast etmek gerekir.

java:com/env Nedir ? 
Aynı JVM içinde çalışan container'a erişmek için kullanıılır. Açıklaması şöyle
It's an in-memory global hashtable where you can store global variables by name.
Örnek
Şöyle yaparız
Context envContext = (Context)initContext.lookup("java:comp/env");
Rastgelen Nesne
Örnek
Şöyle yaparız.
String foobar = (String) new InitialContext().lookup("java:comp/env/foobar");
RMI
Örnek

Şöyle yaparız.
new InitialContext().lookup("rmi://127.0.0.1:1097/Object");
DataSource
"java:comp/env/jdbc" + DataSource ismi şeklindedir

Örnek
Şöyle yaparız.
DataSource ds = null;
try {
  ds = (DataSource) ctx.lookup("java:/comp/env/jdbc/project");
} catch (NamingException e) {
  e.printStackTrace();
}
Örnek
Şöyle yaparız.
Connection con = null;
try {
  InitialContext context = new InitialContext();
  DataSource ds = (DataSource) context.lookup("java:comp/env/jdbc/TEST"

  con =  ds.getConnection();
} catch (SQLException e) {
  ...
}
Örnek
Şöyle yaparız
InitialContext initialContext = new InitialContext();
DataSource dataSource = (DataSource) initialContext.lookup("java:comp/env/jdbc/myDS");




Bean Validation @GroupSequence Anotasyonu

Örnek Elimizde şöyle bir kod olsun public class SampleRequest {   @NotNull   LocalDate startDate;   @NotNull   LocalDate endDate;   @AssertT...