9 Mart 2023 Perşembe

SpringMVC RestTemplate.getForObject metodu

Giriş
İmzası şöyle
// Without parameters
<T> T getForObject(URI url, Class<T> responseType) // Parameter object list as var args <T> T getForObject(String url, Class<T> responseType, Object... uriVariables) // Parameter object list as a map <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables)
getForObject metodu - Parametresiz
XML veya Json ile nesne elde etmek için kullanılır.
Örnek - Array
Şöyle yaparız.
Computer[] computer = restTemplate.getForObject("http://...", Computer[].class);
Örnek
Şöyle yaparız
Todo[] todos = restTemplate
  .getForObject("https://jsonplaceholder.typicode.com/todos", Todo[].class);

// If we use getForEntity
ResponseEntity<Todo[]> todos = restTemplate
        .getForEntity("https://jsonplaceholder.typicode.com/todos", Todo[].class);
Todo[] todoList = todos.getBody();
System.out.println(todos.getStatusCode().name()); // OK
System.out.println(todos.getStatusCodeValue());   // 200
getForObject metodu - Var arg parametreli
XML veya Json ile nesne elde etmek için kullanılır. Son parametre ?type=Foo şeklindeki url'ye dahil olan parametrelerdir.
Örnek
Şöyle yaparız.
QuoteResponse quoteResponse=    
restTemplate.getForObject("http://quotes.rest/qod.json?category=
{param}", QuoteResponse.class, uriVariables);
Örnek
Şöyle yaparız
String completedStatus = "true";
String userId = "1";

Todo[] todosCompletedOfUser = restTemplate
.getForObject(
 "https://jsonplaceholder.typicode.com/todos?completed={completedStatus}&userId={userId}",
 Todo[].class, completedStatus, userId);
getForObject metodu - Map Parametreli
XML veya Json ile nesne elde etmek için kullanılır. Son parametre yani Map ?type=Foo şeklindeki url'ye dahil olan parametrelerdir.

Örnek - Query Parametes
Şöyle yaparız
Map<String, String> map = new HashMap<>();
map.put("completed", "true");
Todo[] todosCompleted = restTemplate
  .getForObject("https://jsonplaceholder.typicode.com/todos?completed={completed}", 
    Todo[].class, map);
Örnek - Path Parameters
Şöyle yaparız
Map<String, String> map = new HashMap<>(); Todo resource
map.put("id", "1");
Todo todo = restTemplate
    .getForObject("https://jsonplaceholder.typicode.com/todos/{id}", Todo.class, map);
System.out.println(todo);












7 Mart 2023 Salı

SpringWebSocket WebSocketHandler Arayüzü

Giriş
Şu satırı dahil ederiz
import org.springframework.web.reactive.socket.WebSocketHandler;
Örnek
Şöyle yaparız
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.socket.WebSocketHandler;
import org.springframework.web.reactive.socket.WebSocketMessage;
import org.springframework.web.reactive.socket.WebSocketSession;
import reactor.core.publisher.Mono;

import java.util.List;

@Component
public class ReactiveServerWebSocketHandler implements WebSocketHandler {

    @Override
    public @NotNull
    Mono<Void> handle(@NotNull WebSocketSession session) {
        return session.send(session.receive()
                .map(WebSocketMessage::getPayloadAsText)
                .map(session::textMessage)
        );
    }

    @Override
    public @NotNull
    List<String> getSubProtocols() {
        return WebSocketHandler.super.getSubProtocols();
    }
}

6 Mart 2023 Pazartesi

SpringRetry UniformRandomBackOffPolicy Sınıfı

Örnek
Şöyle yaparız
import org.springframework.retry.RetryPolicy;
import org.springframework.retry.backoff.BackOffPolicy;
import org.springframework.retry.backoff.UniformRandomBackOffPolicy;
import org.springframework.retry.support.RetryTemplate;

public class PayApiRetryTemplate extends RetryTemplate implements InitializingBean {

  @Override
  public void afterPropertiesSet() throws Exception {
    this.setBackOffPolicy(backOffPolicyWithJitter());
    this.setRetryPolicy(...);
  }

  private BackOffPolicy backOffPolicyWithJitter() {
    UniformRandomBackOffPolicy policy = new UniformRandomBackOffPolicy();
    policy.setMaxBackOffPeriod(this.prop.getRetry().getMaxBackoff());
    policy.setMinBackOffPeriod(this.prop.getRetry().getMinBackoff());
    return policy;
  }
}

5 Mart 2023 Pazar

SpringData Flyway application.properties

baseline-on-migrate Alanı
Eğer şu hatayı alıyorsak
Use baseline() or set baselineOnMigrate to true to initialize the schema history table
Şöyle yaparız
spring: 
 flyway: 
 baseline-on-migrate: true
baseline-version Alanı
Şöyle yaparız
spring: 
 flyway: 
 baseline-on-migrate: true 
 baseline-version: 0
Açıklaması şöyle
If not, the scripts named V1__xxxx.sql would not execute. as the baseline-version default is version 1.
callbacks Alanı
Örnek
Şöyle yaparız
spring:
  flyway:
    enabled: true
    schemas: public
    baseline-on-migrate: true
    baseline-version: 0
    clean-disabled: true
    validate-on-migrate: true
    locations: classpath:db.migration
    placeholderReplacement: false
    callbacks: com.xxx.CsvUpsertCallback
SpringData Flyway Callbacks yazısına bakınız

clean-disabled Alanı
Örnek
Şöyle yaparız
spring: 
 flyway: 
 clean-disabled: true
debug
Örnek
Şöyle yaparız
logging: 
 level: 
 root: INFO 
 org: 
 flywaydb: DEBUG
locations Alanı
Normalde classpath:db/migration dizinini taranır.  Çıktısı şöyle
ClassPathScanner : Unable to resolve location classpath:db/callback.
ClassPathScanner : Scanning for classpath resources at 'classpath:db/migration' …
...
Örnek
Şöyle yaparız. Burada flyway'in arayacağı scriptlerin dizini belirtiliyor.
flyway:
  datasources:
    default:
      enabled: true
      baseline-on-migrate: true
      locations: classpath:db/mymigration
group Alanı
Açıklaması şöyle
The property spring.flyway.group set to true indicates we want to run the pending migrations in a single transaction instead of one transaction per pending migrations. So if one migration fails, all the executed migrations before will be rollbacked.
Örnek
Şöyle yaparız
spring.flyway.enabled=true
spring.flyway.url=jdbc:mysql://localhost:3307/blog?serverTimezone=UTC&useSSL=false
spring.flyway.user=root
spring.flyway.password=secretpswd
spring.flyway.group=true
schemas Alanı
Örnek
Şöyle yaparız
# Flyway properties
spring.flyway.enabled=true
spring.flyway.url=YOUR_DB_URL
spring.flyway.password= YOUR_DB_PASSWORD
spring.flyway.user= YOUR_DB_USERNAME
spring.flyway.schemas=migrations
spring.flyway.locations=classpath:db/migration/postgresql
Örnek
Şöyle yaparız
spring: 
 flyway: 
 placeholders: 
 mySchema: yourSchema
Şöyle yaparız
CREATE TABLE ${mySchema}.template 
( 
 id bigint NOT NULL, 
 code character varying(255) NOT NULL, 
 PRIMARY KEY (id) 
);

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;
  }
}