Şeklen şöyle
14 Temmuz 2023 Cuma
SpringData Reactive ReactiveCrudRepository Arayüzü
13 Temmuz 2023 Perşembe
SpringKafka Consumer RetryTopicConfigurationSupport Sınıfı
Giriş
Açıklaması şöyle
When Using @RetryableTopic for methods annotated with KafkaListener, provide a @Configuration class extends RetryTopicConfigurationSupport .
Örnek
Şöyle yaparız
@Configuration
@RequiredArgsConstructor
@EnableScheduling
@Slf4j
public class KafkaConfig extends RetryTopicConfigurationSupport {
@Override
protected void configureBlockingRetries(BlockingRetriesConfigurer blockingRetries) {
blockingRetries
.retryOn(IOException.class)
.backOff(new FixedBackOff(5000, 3));
}
}SpringKafka Consumer @DltHandler Anotasyonu
Örnek
Şöyle yaparız.
import org.springframework.kafka.annotation.DltHandler;@Slf4j@RequiredArgsConstructor@Componentpublic class UpdateItemConsumer {...@DltHandlerpublic void dlt(String data, @Header(KafkaHeaders.RECEIVED_TOPIC) String topic) {log.error("Event from topic "+topic+" is dead lettered - event:" + data);}}
Örnek
Şöyle yaparız.
@DltHandler
public void processMessage(OrderEvent message) {
log.error("DltHandler processMessage = {}", message);
}5 Temmuz 2023 Çarşamba
SpringWebFlux Flux.onErrorReturn metodu - Exception Olursa Yeni Bir Sonuç Döner
Giriş
Flux kapatılır
Şöyle yaparız
Flux<String> stringFlux = Flux.just("Hello", "World", "from", "IntelliJ IDEA").map(s -> {if (s.equals("World")) throw new RuntimeException("An error occurred");else return s.toUpperCase();});stringFlux.onErrorReturn("Error occurred in the stream.").subscribe(System.out::println);
Çıktı şöyle
HELLO Error occurred in the stream.
Örnek
Şöyle yaparız
Flux<Integer> numbers = Flux.just(1, 2, 3, 4, 5)
.concatWith(Flux.error(new RuntimeException("Oops! An error occurred.")))
.map(number -> 10 / (number - 3)) // This will cause an ArithmeticException
.doOnError(throwable -> System.err.println("Error occurred: " + throwable.getMessage()))
.onErrorReturn(-1); // Provide a fallback value in case of an error
numbers.subscribe(
value -> System.out.println("Received: " + value),
error -> System.err.println("Subscriber error: " + error.getMessage())
);SpringDoc OpenAPI OpenAPI Sınıfı
addSecurityItem metodu
Örnek
Şöyle yaparız
@Bean
public OpenAPI customizeOpenAPI() {
String securitySchemeName = "bearerAuth";
return new OpenAPI()
.addSecurityItem(new SecurityRequirement().addList(securitySchemeName))
.components(
new Components()
.addSecuritySchemes(securitySchemeName,
new SecurityScheme()
.name(securitySchemeName)
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")
)
);
}addServerItems metodu
Örnek
Şöyle yaparız
@Beanpublic OpenAPI customOpenAPI() { return new OpenAPI() .addServersItem(new Server().url("https://myserver.com")) .addServersItem(new Server().url("https://google.com")) .components( new Components() .addSecuritySchemes("basicScheme",new SecurityScheme() .type(SecurityScheme.Type.HTTP) .scheme("basic")) ) .info( new Info() .title("SpringShop API") .version("0.0.1") .license(new License().name("Apache 2.0").url("http://springdoc.org")) ); }
Örnek
Şöyle yaparız
@Bean
public OpenAPI openApiInformation() {
Server localServer = new Server()
.url("http://localhost:8080")
.description("Localhost Server URL");
Contact contact = new Contact()
.email("niket.agrawal90@gmail.com")
.name("Niket Agrawal");
Info info = new Info()
.contact(contact)
.description("Spring Boot 3 + Open API 3")
.summary("Demo of Spring Boot 3 & Open API 3 Integration")
.title("Spring Boot 3 + Open API 3")
.version("V1.0.0")
.license(new License().name("Apache 2.0").url("http://springdoc.org"));
return new OpenAPI().info(info).addServersItem(localServer);
}http://localhost:8080/swagger-ui/index.html adresindeki ekran görüntüsü şöyle
externalDocs metodu
Örnek
Şöyle yaparız
@Bean
public OpenAPI springOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("Micro service")
.description("APIs for Test Console service")
.version("1.0")
.license(new License().name("Dev Team").url("https://github.com")))
.externalDocs(new ExternalDocumentation()
.description("Test Documentation")
.url("https://github.com"));
}info metodu
Örnek
Şöyle yaparız
import io.swagger.v3.oas.models.OpenAPI;import io.swagger.v3.oas.models.info.Info;import io.swagger.v3.oas.models.info.License;@Configurationclass OpenApiConfig {@Beanpublic OpenAPI customOpenAPI(@Value("${application-description}")String appDesciption,@Value("${application-version}")String appVersion) {return new OpenAPI().info(new Info().title("sample application API").version(appVersion).description(appDesciption).termsOfService("http://swagger.io/terms/").license(new License().name("Apache 2.0").url("http://springdoc.org")));}}
4 Temmuz 2023 Salı
SpringAOP PerformanceMonitorInterceptor Sınıfı
Giriş
Şu satırı dahil ederiz
import org.springframework.aop.interceptor.PerformanceMonitorInterceptor;
Açıklaması şöyle
When you enable the “PerformanceMonitorInterceptor,” it quietly observes your code and collects essential information, such as the execution time of different methods. It keeps a record of how much time is spent in each method, which is incredibly helpful in identifying bottlenecks or areas where your code might be slowing down.Having access to this information allows you to analyze and optimize your code to make it faster and more efficient. For example, if you discover that a particular method is taking too much time to execute, you can focus on optimizing that specific part of your code to improve overall performance.Moreover, the “PerformanceMonitorInterceptor” enables you to measure the performance of your code across multiple requests or interactions. This broader perspective helps you understand how your application is performing over time, rather than relying on isolated measurements.
Maven
Şu satırı dahil ederiz
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
AbstractMonitoringInterceptor sınıfından kalıtır. Loglama ayarları için şöyle yaparız
logging.level.dev.knowledgecafe=TRACE logging.level.org.springframework.aop.interceptor.PerformanceMonitorInterceptor=TRACE
Örnek
Şöyle yaparız
@Configuration@EnableAspectJAutoProxypublic class AopConfiguration {@Pointcut("execution(public String foo.EmployeeService.getFullName(..)))")public void monitor() { }@Beanpublic PerformanceMonitorInterceptor performanceMonitorInterceptor() {return new PerformanceMonitorInterceptor(true);}@Beanpublic Advisor performanceMonitorAdvisor() {AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();pointcut.setExpression("dev.knowledgecafe.performance_trace.AopConfiguration.monitor()");return new DefaultPointcutAdvisor(pointcut, performanceMonitorInterceptor());}}
27 Haziran 2023 Salı
SpringMVC Declarative REST Client - OpenFeign Yerine Kullanılır
Giriş
OpenFeign yerine kullanılır. Açıklaması şöyle
HTTP Interface Client introduced in Spring 6. The HTTP Interface Client enables to definition a declarative way for HTTP services using Java interfaces. Under the hood, Spring generates a proxy class that implements the interface and performs exchanges.
Bağımlılıklar
Açıklaması şöyle
All necessary components are in the spring-web module, that happens to be a transitive dependency for the spring-boot-starter-web or the spring-boot-starter-webflux modules. However, in practice the WebFlux dependency is always required at the moment due to the HttpServiceProxyFactory for generating the clients.
Açıklaması şöyle
Why do you need Spring Reactive Web dependenciesWhen 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.
Anotasyonlar
Anotasyonlar şöyle
@HttpExchange
@PutExchange
@DeleteExchange
baseUrl metodu
İsteğin gönderileceği URL adresini belirtir
Örnek
Şöyle yaparız
public interface CatFactsClient {
@GetExchange(value = "/facts")
List<Fact> getFacts();
}
@Configuration
public class CatFactsClientConfig {
@Bean
public CatFactsClient catFactsClient() {
WebClient client = WebClient.builder()
.baseUrl("https://cat-fact.herokuapp.com")
.build();
HttpServiceProxyFactory factory = HttpServiceProxyFactory
.builder(WebClientAdapter.forClient(client))
.build();
return factory.createClient(CatFactsClient.class);
}
}
@Service
public class MyService {
@Autowired
private CatFactsClient catFactsClient;
public List<Fact> fetchCatFacts() {
return catFactsClient.getFacts();
}
}clientConnector metodu
Örnek - WebClient Connection reset by peer error
Gönderilen istekler için keep-alive seçeneğini kapatmak gerekir. Şöyle yaparız
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.support.WebClientAdapter;
import org.springframework.web.service.invoker.HttpServiceProxyFactory;
import reactor.netty.http.client.HttpClient;
@Configuration
public class HttpProxyConfiguration {
@Value("${tracker.url}")
private String trackerUrl;
@Bean
TrackerClient trackerClient(WebClient.Builder builder) {
var httpClient = HttpClient.newConnection().keepAlive(false); // Here
var reactorClientHttpConnector = new ReactorClientHttpConnector(httpClient);
var wc = builder.baseUrl(trackerUrl)
.clientConnector(reactorClientHttpConnector)
.build();
var wca = WebClientAdapter.forClient(wc);
return HttpServiceProxyFactory.builder()
.clientAdapter(wca)
.build()
.createClient(TrackerClient.class);
}
}defaultStatusHandler metodu
HttpStatus.NOT_FOUND, HttpStatusCode::is5xxServerError gibi durumlarda ne yapılacağını belirtir
Örnek
Elimizde şöyle bir kod olsun
@HttpExchange(url = "/characters",accept = MediaType.APPLICATION_JSON_VALUE)public interface CharacterClient {@GetExchangeList<CharacterResponse> getByName(@RequestParam String lastName);@GetExchange("/{id}")Optional<CharacterResponse> getById(@PathVariable long id);@PutExchange(contentType = MediaType.APPLICATION_JSON_VALUE)CharacterResponse addCharacter(@RequestBody AddCharacterRequest request);@DeleteExchange("/{id}")void deleteById(@PathVariable long id);}
Bu arayüzden Spring kod üretir. Daha sonra bu kodu WebClient ile birleştirmek gerekir. Şöyle yaparız
@Configuration
public class CharacterClientConfig {
@Bean
public CharacterClient characterClient(CharacterClientProperties properties) {
WebClient webClient = WebClient.builder()
.baseUrl(properties.getUrl())
.defaultStatusHandler(
httpStatusCode -> HttpStatus.NOT_FOUND == httpStatusCode,
response -> Mono.empty())
.defaultStatusHandler(
HttpStatusCode::is5xxServerError,
response -> Mono
.error(new ExternalCommunicationException(response.statusCode().value())))
.build();
return HttpServiceProxyFactory
.builder(WebClientAdapter.forClient(webClient))
.build()
.createClient(CharacterClient.class);
}
}
@Data
@Component
@ConfigurationProperties("character-client")
public class CharacterClientProperties {
private String url;
}Açıklaması şöyle. Yani şimdilik HttpServiceProxyFactory + WebClientAdapter + WebClient kodunu elle yazmak gerekiyor.
Currently, unlike OpenFeign, the client is not yet supplied via auto-configuration in a Spring Boot setup (kindly track Support declarative HTTP clients #31337 for that matter). Therefore, we build a WebClient ourselves and create a declarative HTTP client from it by using the createClient method from HttpServiceProxyFactory. This is some kind of boilerplate code, but I am quite confident that the Spring Boot guys will come up with a nice solution to simplify this further. Up until this point, you will need such a bean definition for each declarative HTTP client in your application.
Kullanmak için şöyle yaparız
CharacterResponse brandon = characterClient
.addCharacter(new AddCharacterRequest("Brandon", "Stark"));
List<CharacterResponse> starks = characterClient.getByName("Stark");
Optional<CharacterResponse> eddardStark = characterClient.getById(1);
Optional<CharacterResponse> unknown = characterClient.getById(1337L); // empty
characterClient.deleteById(brandon.id());Eğer Sadece Web Client Kullansaydık şöyle yaparız. Bu da karışık kodlar demek
public List<CharacterResponse> getByName(String lastName) {
return webClient
.get()
.uri(uriBuilder -> uriBuilder
.path("/characters")
.queryParam("lastName", "{lastName}")
.build(lastName))
.retrieve()
.toEntityList(CharacterResponse.class)
.block()
.getBody();
}
Kaydol:
Kayıtlar (Atom)

