diff --git a/_drafts/2024-09-17-Java-Streams-Gather-Jdk-23.markdown b/_drafts/2024-09-17-Java-Streams-Gather-Jdk-23.markdown new file mode 100644 index 00000000..4c4566fa --- /dev/null +++ b/_drafts/2024-09-17-Java-Streams-Gather-Jdk-23.markdown @@ -0,0 +1,73 @@ +--- +layout: post +title: "Jdk 23 Streams - Using Gather" +toc: true +date: 2024-09-17 12:00:00 -0500 +categories: +- software +- java +--- + +# It's finally here! JDK 23 +TODO - make small XXXTODOXXX + +Just kidding, this isn't an LTS release + +The next LTS release that will include all of the changes in JDK 23 is XXXTODOXXX and +that won't be available until XXXTODOXXX + +The link to the release notes for Jdk23 are right here: https://openjdk.org/projects/jdk/23/ + +But this article is going to focus on a pretty powerful addition for anyone that's been +leveraging Java Streams heavily for stream processing! + +Specifically Gatherers, the JEP is right over here: https://openjdk.org/jeps/473 + +## JEP-473 + +Stream Gatherers is a preview API delivered in JDK 22 that's in preview again +in JDK 23. Gatherers allow for stream pipelines to transform +data through intermediate operations instead of needing to perform +a terminating operation and generate a new stream. + +Today, if we want to process a list of elements, then perform an operation on the entire list, +and then continue processing the list, we'd have to do it like this: + +```java +TODO - add an example here +``` +With Gatherers, we're able to do this in a cleaner way by +doing our extra processing in an intermediate method! + +```java +TODO - add an example here +``` + +Here's the full example code (and we don't need a default class anymore with JDK 23!) + +```java +import java.util.function.Predicate; +import java.util.stream.Gatherer; +import java.util.stream.Stream; + +void main(String[] args) { + + var result = Stream.of(1, 2, 3) // The Stream + .filter((integer -> integer > 0)) // Intermediate Operation + // TODO - gather example + .toList(); // The Terminal Operation + System.out.println(result); +} + +``` + +```bash + $ javac demo.java --enable-preview -source 23 + $ java --enable-preview demo +``` + +TODO - find real life example +- distinctBy +- grouping and applying a change to the whole collection + +[soby-chako]: https://github.com/sobychacko diff --git a/_posts/2024-09-19-Easy-Spring-Rest-Client-with-OAuth2.markdown b/_posts/2024-09-19-Easy-Spring-Rest-Client-with-OAuth2.markdown new file mode 100644 index 00000000..9b4e7504 --- /dev/null +++ b/_posts/2024-09-19-Easy-Spring-Rest-Client-with-OAuth2.markdown @@ -0,0 +1,187 @@ +--- +layout: post +title: "Easy Spring Rest Client w/ OAuth2" +toc: true +date: 2024-09-19 12:00:00 -0500 +categories: +- software +- spring boot +- java +--- + +# Brief + +My goal is to make posts like this the SIMPLEST place on the internet to learn how to do things +that caused me trouble. That way, if this is found, someone doesn't have to do the same digging I had to do. + +# What is OAuth2? + +OAuth2 is a popular authorization framework that allows users to grant +third-party applications access to their data without revealing their +credentials. It's often used for services like social media logins, API integrations, and more. + +### Key Components of OAuth2 + +- Authorization Server: Issues access tokens to clients after user authorization. +- Resource Server: Protects resources that can only be accessed with valid access tokens. +- Client: The application requesting access to resources. +- User: The person granting or denying access. + +### How OAuth2 Works + +- User Authorization: The user grants permission to the client to access specific resources. +- Token Exchange: The client exchanges an authorization code for an access token. +- Resource Access: The client uses the access token to access protected resources. + +### Why RestClient? + +While **RestTemplate** has been a staple for many years, its limitations and the +introduction of more modern alternatives have led to its deprecation in recent +versions of Spring. Let's dive into the key differences between WebClient +and RestClient and why RestTemplate is being phased out. + +**WebClient** is built on top of Project Reactor, a reactive +programming framework. This means it can handle asynchronous operations efficiently, +making it well-suited for scenarios where concurrent requests and non-blocking I/O +are essential. + +However, with RestTemplate's deprecation, the only real Spring alternative is WebClient. +This requires including the spring-webflux dependencies and calling `.block()` when making +blocking API calls. It feels shoe-horned into place. + +In comes [RestClient][restClientBlogAnnouncement], a client written in the same functional style as WebClient, but supports +synchronous and asynchronous operations out of the box. This lets us remove the spring-webflux +dependency and use spring-web-mvc as the primary HTTP dependency for server and client applications. + +## The Setup (Currently a Milestone Release but this will be updated!) + +Here's everything you need to get RestClient working with OAuth2! + +build.gradle +```groovy +plugins { + id 'org.springframework.boot' version '3.3.3' +} + + // ... The rest of the stuff, this is just what's required + + dependencies { + implementation 'org.springframework.boot:spring-boot-starter-security' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.security:spring-security-oauth2-client:6.4.0-M3' + } +} +``` + +application.yaml +```yaml +spring: + security: + oauth2: + client: + registration: + my-oauth-client: + client-id: ${oauthClientId} + client-secret: ${oauthClientSecret} + provider: my-oauth-provider + authorization-grant-type: client_credentials + scope: openid + provider: + my-oauth-provider: + token-uri: ${oauth2ServerUri}/protocol/openid-connect/token + issuer-uri: ${oauth2ServerUri} +``` + +application-local.yaml +```yaml +oauth2ServerUri: http://myServerUri:9090 +oauthClientId: clientId +oauth2ClientSecret: mySecretSecret +``` + +RestClientConfiguration.java using the new [OAuth2ClientHttpRequestInterceptor][oAuth2ClientHttpRequestInterceptor] +```java +@Configuration +public class RestClientConfiguration +{ + // This needs to match the YAML configuration + private static final String CLIENT_REGISTRATION_ID = "my-oauth-client"; + + @Bean + public OAuth2AuthorizedClientManager authorizedClientManager ( + ClientRegistrationRepository clientRegistrationRepository, + OAuth2AuthorizedClientService authorizedClientService + ){ + // We create a manager using the autowired clientRegistrations from YAML and connect it to the service + AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager = + new AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientService); + + // Setting the clientManager to look for a clientCredentials configuration + authorizedClientManager.setAuthorizedClientProvider(OAuth2AuthorizedClientProviderBuilder.builder() + .clientCredentials() + .build()); + return authorizedClientManager; + } + + @Bean + public RestClient oauth2RestClient( + OAuth2AuthorizedClientManager authorizedClientManager, + LogbookClientHttpRequestInterceptor logbookClientHttpRequestInterceptor) { + + // This is the new class!!! We instantiate a new one and provide it the client registration to match + OAuth2ClientHttpRequestInterceptor oAuth2ClientHttpRequestInterceptor = + new OAuth2ClientHttpRequestInterceptor(authorizedClientManager, request -> CLIENT_REGISTRATION_ID); + + // From here we simply return the client with any custom configuration, and we're good to go! + return RestClient.builder() + .baseUrl("http://myBaseUrl:8080") + .requestInterceptor(oAuth2ClientHttpRequestInterceptor) + .build(); + } +} +``` + +### Bonus: Setting up HttpServiceProxyFactory (not required but useful!) + +[HttpServiceProxyFactory][httpServiceProxyFactory] is new in [Spring 6][httpServiceProxyFactoryJavadoc]! + +```java +public interface MyHttpService { + + @PostExchange("api/my/path") + SomeResponse post(@RequestBody MyPostBody request); +} +``` + +```java +@Configuration +public class HttpServiceFactory +{ + @Bean + public MyHttpService getMyHttpService(RestClient oauth2RestClient) { + // We're simply injecting our restClient into the factory and creating a concrete instance of the interface + HttpServiceProxyFactory factory = HttpServiceProxyFactory + .builderFor(RestClientAdapter.create(oauth2RestClient)) + .build(); + return factory.createClient(MyHttpService.class); + } +} +``` + +## Summary + +The new RestClient is already a popular alternative for developers in the Spring ecosystem. +The lack of an OAuth2 component has been a sore spot for new users converting over from WebClient. So with +this new feature releasing in Spring Boot 3.4.0, it can now take it's rightful place as the default, non-webflux +HTTP Client for Spring MVC! + +## Update Note + +Once this is available in the official spring release, I'll update this from milestone versions and +hook up the JavaDoc instead of the originating Github Issue! + +[restClientBlogAnnouncement]: https://spring.io/blog/2023/07/13/new-in-spring-6-1-restclient +[oAuth2ClientHttpRequestInterceptor]: https://github.com/spring-projects/spring-security/issues/13588 +[httpServiceProxyFactoryJavadoc]: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/service/invoker/HttpServiceProxyFactory.html +[httpServiceProxyFactory]: https://www.baeldung.com/spring-6-http-interface +[soby-chako]: https://github.com/sobychacko