News

Java Annotated Monthly – November 2025

This edition is packed with insightful, practical, and curiosity-fueling reads. From hands-on advice to thought-provoking pieces, we’ve gathered a nice selection of stories that will help you stay sharp and inspired in the tech world.

We’re also happy to have Josh Long as our featured content author this month! Expect some top-notch insights and a good dose of Spring.

So, grab your coffee and dive in – there’s plenty worth reading inside!

Featured Content

Josh Long

Josh Long works on the Spring team as its number one fan. You can find more of his content – blogs, Youtube content, podcasts, etc. – on his website.

Hi, Spring fans! Spring Boot 4 comes out in November 2025! With this in mind, lLet’s at least look at some of my favorite features together. Jakarta EE 11 is the new baseline. We’ve retained a Java 17 baseline but strongly encourage a Java 25 posture whenever possible. We’ve moved the baseline to GraalVM 25 for native images and updated our Kotlin support to Kotlin 2.2. The new generation of projects assumes the new Jackson 3. We’ve introduced JSpecify nullability annotations across the portfolio to finally eliminate Tony Hoare’s $1 billion dollar mistake – null references. Spring Boot 4 has decomposed the autoconfiguration artifact into smaller, more modular autoconfigurations.

One of my favorite new features is API versioning. Here’s a Spring MVC controller with two endpoints, each designated a particular version, the default version of which we can specify with spring.mvc.apiversion.default=1.1.

@RestController

class DogsController {

    ...

    @GetMapping(value = "/dogs",version="1.0")

    Collection<Map<String, Object>> dogsClassic() {

        ... 

    }

    @GetMapping(value = "/dogs", version = "1.1")

    Collection<Dog> dogs() {

        ... 

    }

}

I also love the new easy-mode declarative HTTP clients. Let’s build a client to talk to the Cat Facts API and then activate it using @ImportHttpServices(CatFacts.class):

record CatFact(@JsonProperty("fact_number") int factNumber, String fact) { }

record CatFactsResponse(Collection<CatFact> facts) { }

interface CatFacts {

    @GetExchange("https://www.catfacts.net/api")

    CatFactsResponse facts();

}

We built a simple client, and it should work, but what if the service is down? In this case, we can enable resilient methods with Spring’s new @EnableResilientMethods annotation. This gives us two new features: @ConcurrencyLimit and @Retryable (and the related RetryTemplate).

...

    @ConcurrencyLimit(10)

    @Retryable(maxAttempts = 4, includes = BadException.class)

    @GetMapping("/facts")

    Collection<CatFact> facts()  throws Exception {

        ...

    }

    ...

   

Spring Framework 7 brings BeanRegistrar configuration, which is a more dynamic alternative to Java configuration that can be used in conjunction with Java configuration and component scanning with the usual @Import annotation.

class MyBeanRegistrar implements BeanRegistrar {

    @Override

    public void register(BeanRegistry registry, Environment env) {

        registry.registerBean(Runner.class);

        registry.registerBean(Runner.class, spec -> spec

                .description("description")

                .supplier(supplierContext -> new Runner(

                        supplierContext.bean(DogRepository.class), supplierContext.beanProvider(CatFacts.class)

                        .getIfUnique())

                ));

    }

}

Spring Security brings with it a lot of nice new features. Two of my favorites are multi-factor auth, allowing you to require that multiple authentication factors be present, and Customizer<HttpSecurity> beans for additive changes to the HttpSecurity configuration.

@EnableGlobalMultiFactorAuthentication(

    authorities = { FactorGrantedAuthority.PASSWORD_AUTHORITY, FactorGrantedAuthority.OTT_AUTHORITY })

@Configuration

class SecurityConfiguration {

    @Bean

    Customizer<HttpSecurity> httpSecurityCustomizer() {

        return httpSecurity -> httpSecurity

                .webAuthn(w -> ... )

                .oneTimeTokenLogin(ott -> ... );

    }

}

The code is here for your reference. I encourage users to kick the tires and try everything out on the Spring Initializer – and enjoy your journey to production!

Java News

Stay in the loop with the latest from the Java world:

Java Tutorials and Tips

Keep exploring pro tips that make your Java experience even better:

Kotlin Corner

Your dose of Kotlin news and tips is here:

AI 

Don’t miss what’s buzzing in the AI world:

Languages, Frameworks, Libraries, and Technologies

Explore everything new and exciting in tech right here:

Conferences and Events

Plan your visits:

Culture and Community

Let the articles below spark some inspiration and reflection:

That’s it for today! We’re always collecting ideas for the next Java Annotated Monthly – send us your suggestions via email or X by November 20. Don’t forget to check out our archive of past JAM issues for any articles you might have missed!

image description