27 Şubat 2023 Pazartesi

SpringMVC @GetExchange Anotasyonu - OpenFeign Yerine Kullanılır

Giriş
Şu satırı dahil ederiz
import org.springframework.web.service.annotation.GetExchange;
Açıklaması şöyle
Why do you need Spring Reactive Web dependencies
When creating the project above, the dependency of Spring Reactive Web was introduced, and the WebClient type was used when creating the service object of the proxy. This is because HTTP Interface currently only has built-in implementation of WebClient, which belongs to the category of Reactive Web. Spring will launch a RestTemplate-based implementation in subsequent versions.
Örnek
Şöyle yaparız
interface UsersClient {
@GetExchange("/users") User findByFirstName(@RequestParam("firstName") String firstName); }
Örnek
Elimizde şöyle bir REST kodu olsun
public class User implements Serializable {
  ...
}

@GetMapping("/users")
public List<User> list() {
    return IntStream.rangeClosed(1, 10)
            .mapToObj(i -> new User(i, "User" + i))
            .collect(Collectors.toList());
}
Şöyle yaparız
public interface UserApiService {
   @GetExchange("/users")
   List<User> getUsers();
}

@Test
void getUsers() {
   WebClient client = WebClient.builder()
    .baseUrl("http://localhost:8080/")
    .build();

  HttpServiceProxyFactory factory = HttpServiceProxyFactory
    .builder(WebClientAdapter.forClient(client))
    .build();

   UserApiService service = factory.createClient(UserApiService.class);
   List<User> users = service.getUsers();
   for (User user : users) {
      System.out.println(user);
   }
}

24 Şubat 2023 Cuma

SpringData Redis Redission Sınıfı

Giriş
Redisson için açıklama şöyle
Redisson adopts the nety framework based on NIO, which can not only be used as the underlying driver client of Redis, but also can send redis commands in synchronous, asynchronous, asynchronous stream or pipeline forms, execute and process Lua scripts, and process the returned results.
Maven
Şu satırı dahil ederiz
<dependency>
   <groupId>org.redisson</groupId>
   <artifactId>redisson</artifactId>
   <version>3.17.6</version>
</dependency>
Örnek
Şöyle yaparız
@RequiredArgsConstructor
@Configuration
public class RedissonConfig {

  @Bean
  public RedissonClient redissionClient() {
    Config config = new Config();
    config.useSingleServer().setAddress("redis://127.0.0.1:6379");
    return Redisson.create(config);
 }

@Bean
public RedisTemplate<String, Object> redisTemplate( RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new JdkSerializationRedisSerializer());
redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
redisTemplate.setEnableTransactionSupport(true);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}

SpringData Redis RedisStandaloneConfiguration Sınıfı

Giriş
Şu satırı dahil ederiz
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
Eğer ayarları application.properties ile yapmak istemiyorsak bu sınıfı yaratmak gerekir. 
Hem LettuceConnectionFactory  hem de JedisConnectionFactory için bu sınıf gerekir

JedisConnectionFactory
Örnek
Şöyle yaparız. Bu kod ile artık RedisTemplate kullanabiliriz.
@Configuration
@EnableRedisRepositories
public class RedisConfig {

  @Bean
  public JedisConnectionFactory connectionFactory(){
    RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
    configuration.setHostName("localhost");
    configuration.setPort(6379);
    return new JedisConnectionFactory(configuration);
  }

  @Bean
  @Primary
  public RedisTemplate<String, Object> redisTemplate(){
    RedisTemplate<String, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(connectionFactory());
    template.setKeySerializer(new StringRedisSerializer());
    template.setHashKeySerializer(new StringRedisSerializer());
    template.setHashKeySerializer(new JdkSerializationRedisSerializer());
    template.setHashValueSerializer(new JdkSerializationRedisSerializer());
    template.setEnableTransactionSupport(true);
    template.afterPropertiesSet();

    return template;
  }
}


22 Şubat 2023 Çarşamba

SpringSession Mongo

Maven
Şu satırı dahil ederiz
<dependency>
   <groupId>org.springframework.session</groupId>
   <artifactId>spring-session-core</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.session</groupId>
   <artifactId>spring-session-data-mongodb</artifactId>
</dependency>
application.properties
Örnek
Şöyle yaparız
spring.data.mongodb.database=sessionDb
spring.data.mongodb.port=27017
spring.data.mongodb.host=localhost 
spring.data.mongodb.authentication-database=admin
spring.data.mongodb.username=admin
spring.data.mongodb.password=password



20 Şubat 2023 Pazartesi

SpringBoot spring.jpa Hibernate'e Özel Ayarlar - Time Zone

Giriş
Açıklaması şöyle
As introduced by this post in the official Hibernate blog, since Hibernate 5.2.3 we can make use of the hibernate.jdbc.time_zone property to make the way dates are stored independent from the JVM’s default timezone.
Örnek
Şöyle yaparız
spring.jpa.properties.hibernate.jdbc.time_zone=UTC
Açıklaması şöyle
The spring.jpa.properties.hibernate.jdbc.time_zone property sets the default timezone to UTC to make it easier to handle timestamps across multiple timezones. For more details about handling timezones with Spring Boot, check out this article.

Spring 3 İçin SpringNative - GraalVM

Giriş
Spring 3 için açıklaması şöyle
It started as an experimental module called Spring Native, to be added to Spring Boot 2.7 apps. But with Spring Boot 3.0, GraalVM support has been brought into the portfolio projects themselves.

No Spring Native project needed.
Şöyle yaparız
For AOT generation, there's no need to include separate plugins, we can just use a new goal of the spring-boot-maven-plugin

mvn spring-boot:aot-generateCopy
1. GraalVM kurulur
2. Projeye GraalVM Native Support eklenir
3. native-maven-plugin eklenir
Örnek
Şöyle yaparız
<build>
  <plugins>
    ...
    <plugin>
      <groupId>org.graalvm.buildtools</groupId>
      <artifactId>native-maven-plugin</artifactId>
    </plugin>
  </plugins>
</build>
Örnek
Tüm pom.xml şöyle. native-maven-plugin bazen farklı bir profile'a da ekleniyor. 
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.0.1</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>
  <groupId>com.example</groupId>
  <artifactId>demo</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>demo</name>
  <description>Demo project for Spring Boot</description>
  <properties>
    <java.version>17</java.version>
  </properties>
  <dependencies>
    ...
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.hibernate.orm.tooling</groupId>
	<artifactId>hibernate-enhance-maven-plugin</artifactId>
	<version>${hibernate.version}</version>
	<executions>
	  <execution>
	    <id>enhance</id>
	      <goals>
	        <goal>enhance</goal>
	      </goals>
	      <configuration>
	        <enableLazyInitialization>true</enableLazyInitialization>
		<enableDirtyTracking>true</enableDirtyTracking>
		<enableAssociationManagement>true</enableAssociationManagement>
	      </configuration>
	    </execution>
	  </executions>
	</plugin>
      <plugin>
        <groupId>org.graalvm.buildtools</groupId>
	<artifactId>native-maven-plugin</artifactId>
      </plugin>
      <plugin>
        <groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>
4. mvn clean package -Pnative çalıştırılır. Açıklaması şöyle. AOT kısaltması Ahead-of-Time anlamına gelir.
Maven has three different goals for AOT processing and building the image:

mvn spring-boot:process-aot

mvn spring-boot:process-test-aot

mvn spring-boot:build-image

But these three commands are combined in the mvn clean package -Pnative.

Quick tip: the profile native is predefined in Spring Boot 3 for the native image creation. The same applies to the profile nativeTest as a testing profile.
Örneğin ./target/demo diye bir dosya oluşur. Bu çalıştırılır
veya şöyle yapılir
./mvnw -Pnative native:compile

./target/<native-executable>
RuntimeHints
@ImportRuntimeHints Anotasyonu yazısına taşıdım

@RegisterReflectionForBinding Anotasyonu

AOT
Şöyle yaparız
$ java -Dspring.aot.enabled=true -jar ldap-service.jar



19 Şubat 2023 Pazar

SpringBoot DataSource application.properties Oracle Ayarları

Örnek
Şöyle yaparız
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:orcl
spring.datasource.username=oracle
spring.datasource.password=password
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
Örnek
Şöyle yaparız.
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:XE
spring.datasource.username=talon
spring.datasource.password=talon

spring.datasource.tomcat.test-while-idle=true
spring.datasource.dbcp2.validation-query=SELECT 1
Örnek
Şöyle yaparız
spring.datasource.driver-class = oracle.jdbc.driver.OracleDriver
spring.datasource.hikari.connection-timeout = 60000
spring.datasource.hikari.maximum-pool-size  = 5
spring.datasource.password = password
spring.datasource.url = jdbc:oracle:thin:@localhost:1521:xe
spring.datasource.username = username

16 Şubat 2023 Perşembe

SpringCloud Retrofit Kullanımı

Giriş
Refrofit kütüphanesi OpenFeign yerine tercih edilebilir

Gradle
Şöyle yaparız
implementation ‘org.springframework.cloud:spring-cloud-square-retrofit:0.4.1’
implementation ‘org.springframework.cloud:spring-cloud-square-okhttp:0.4.1’
Örnek
Şöyle yaparız
@EnableRetrofitClients(basePackages = "com.oguzderici.retrofitdemo.clients")
@Configuration
public class RetrofitConfiguration {

  @Bean
  @LoadBalanced
  public OkHttpClient.Builder okHttpClientBuilder() {
    return new OkHttpClient.Builder()
      .addInterceptor(new HttpLoggingInterceptor()
                        .setLevel(HttpLoggingInterceptor.Level.BASIC));
    }
}
Arayüzler için şöyle yaparız
@RetrofitClient(name = "welcome-service", configuration = AuthenticationConfig.class)
public interface WelcomeRetrofitClient {
  @GET("/v1/whoiam")
  Call<WelcomeResponse> callName(@Query("name") String name);

  @POST("/v1/welcome")
  Call<WelcomeResponse> callSuccess(@Body WelcomeRequest welcomeRequest);

  @PUT("/v1/welcome/{id}")
  Call<WelcomeResponse> callWithFail(@Path("id") String id,
     @Body WelcomeRequest welcomeRequest);

  @DELETE("/v1/welcome/{id}")
  Call<Void> deleteWelcomeRequest(@Path("id") String id);
}

@RequiredArgsConstructor
@Configuration
public class AuthenticationConfig {
  private final TokenInterceptor tokenInterceptor;
  private final AuthenticatorInterceptor authenticatorInterceptor;
  private final HeaderInterceptor headerInterceptor;

  @Bean
  @LoadBalanced
  public OkHttpClient.Builder okHttpClientBuilder() {
    return new OkHttpClient.Builder()
      .addInterceptor(tokenInterceptor)
      .addInterceptor(headerInterceptor)
      .authenticator(authenticatorInterceptor);
  }
}



SpringBoot DataSource application.properties MySQL Ayarları

Örnek
Şöyle yaparız.
spring.datasource.url=jdbc:mysql://localhost/mydb
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
Örnek
Şöyle yaparız.
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/web_customer_tracker
spring.datasource.username=springstudent
spring.datasource.password=springstudent
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url-base=jdbc:mysql://localhost:3306
spring.datasource.url=${spring.datasource.url-base}/cloud_school
spring.datasource.username=root
spring.datasource.password=root
Örnek
Şöyle yaparız
# application.properties
spring.datasource.url=jdbc:mysql://localhost/appdb
spring.datasource.username=user
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

# application.yml
spring:
  datasource:
    url: jdbc:mysql://localhost/mydb
    username: user
    password: password
    driver-class-name: com.mysql.jdbc.Driver