{"id":142557,"date":"2026-04-08T09:28:00","date_gmt":"2026-04-08T06:28:00","guid":{"rendered":"https:\/\/www.javacodegeeks.com\/?p=142557"},"modified":"2026-04-03T21:38:09","modified_gmt":"2026-04-03T18:38:09","slug":"spring-boot-4-vs-3-what-actually-changed","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2026\/04\/spring-boot-4-vs-3-what-actually-changed.html","title":{"rendered":"Spring Boot 4 vs. 3: What Actually Changed"},"content":{"rendered":"<p><em>The migration guides list dozens of changes. Most articles rehash the changelog. This piece focuses on the three changes that will meaningfully alter how you design APIs in 2026: built-in API versioning, null-safe annotations from JSpecify, and Jackson 3 defaults that will silently break your serialization tests.<\/em><\/p>\n<h2 class=\"wp-block-heading\" id=\"context\">1. What This Release Actually Is<\/h2>\n<p>Spring Boot 4 and Spring Framework 7 went GA on November 20, 2025. The marketing framing is &#8220;next generation,&#8221; which typically means modest improvement. This time it&#8217;s more accurate. The release modularises the entire Spring Boot codebase into 70+ focused JARs, mandates Jackson 3 as the JSON library, and ships three significant additions that change how you&#8217;ll write Java APIs going forward.<\/p>\n<p>The Java baseline stays at 17, which is the right call \u2014&nbsp;<a href=\"https:\/\/www.infoq.com\/news\/2025\/11\/spring-7-spring-boot-4\/\" target=\"_blank\" rel=\"noreferrer noopener\">as Juergen Hoeller told InfoQ<\/a>, &#8220;the current industry consensus is clearly around a Java 17 baseline.&#8221; First-class support for Java 25 is included, meaning AOT compilation and GraalVM native images are tested on Java 25 and take advantage of its capabilities. The Jakarta EE baseline moves to 11, which means Hibernate must upgrade to 7.x, Bean Validation to 3.1, and Tomcat to 11. If you have any&nbsp;<code>javax.*<\/code>&nbsp;imports that somehow survived Boot 3, they will not survive Boot 4.<\/p>\n<p>The other removals are concrete:&nbsp;<strong>JUnit 4 is gone<\/strong>,&nbsp;<strong>Undertow is removed<\/strong>, and&nbsp;<strong>all Boot 3 deprecations have been cleared<\/strong>. The recommended upgrade path is to go through Spring Boot 3.5 first, eliminate every deprecation warning, then migrate to 4.0. Any deprecated API that made it to 3.5 is fully deleted in 4.0, with no fallback.<\/p>\n<p><strong>The right migration path<\/strong><\/p>\n<p>Spring Boot 3.5 \u2192 fix every deprecation warning \u2192 Spring Boot 4.0. Do not jump directly from 3.2 or 3.3. The Boot team aligned 3.5 specifically to be a clean stepping stone. Any deprecated API that survived into 3.5 is absent from 4.0 without exception.<\/p>\n<h2 class=\"wp-block-heading\" id=\"versioning\">2. API Versioning: The Feature That Changes How You Write Controllers<\/h2>\n<p>Before Spring Boot 4, versioning a REST API in Spring required one of three hacks: URL path duplication (<code>\/api\/v1\/users<\/code>&nbsp;and&nbsp;<code>\/api\/v2\/users<\/code>&nbsp;as separate controller classes), custom request interceptors that parsed a header and routed accordingly, or content negotiation overloading. None of these were framework-first concepts; they were conventions imposed on top of Spring&#8217;s request mapping infrastructure.<\/p>\n<p>Spring Framework 7 makes versioning a first-class part of request mapping. The new&nbsp;<code>version<\/code>&nbsp;attribute is available on&nbsp;<code>@GetMapping<\/code>,&nbsp;<code>@PostMapping<\/code>, and all other mapping annotations. A single controller class can now serve multiple versions of the same endpoint with no duplication of the routing path.<\/p>\n<pre class=\"brush:java\">\n@Configuration\npublic class WebConfig implements WebMvcConfigurer {\n    @Override\n    public void configureApiVersioning(ApiVersionConfigurer configurer) {\n        configurer\n            .useRequestHeader(\"API-Version\")   \/\/ resolve from header\n            .setVersionRequired(true)            \/\/ reject unversioned requests\n            .addSupportedVersions(\"1.0\", \"1.1\", \"2.0\");\n    }\n}\n\n@RestController\n@RequestMapping(\"\/accounts\")\npublic class AccountController {\n\n    \/\/ Serves requests with API-Version: 1.0\n    @GetMapping(version = \"1.0\")\n    public AccountV1 getAccountV1() { ... }\n\n    \/\/ Serves 1.1 and later (until a higher version takes over)\n    @GetMapping(version = \"1.1+\")\n    public AccountV2 getAccountV1Plus() { ... }\n\n    \/\/ Serves requests with API-Version: 2.0\n    @GetMapping(version = \"2.0\")\n    public AccountV3 getAccountV2() { ... }\n}\n<\/pre>\n<h3 class=\"wp-block-heading\">The four versioning strategies<\/h3>\n<p>The&nbsp;<code>ApiVersionConfigurer<\/code>&nbsp;supports four resolution strategies, selectable per application. Path-segment versioning (<code>usePathSegment(1)<\/code>) reads the version from a specific URL path index. Header versioning (<code>useRequestHeader(\"API-Version\")<\/code>) is the default recommended approach for new APIs. Query parameter versioning (<code>useQueryParam(\"version\")<\/code>) is available for teams that prefer URL-only versioning. Media type versioning (<code>useMediaTypeParameter(\"v\")<\/code>) supports&nbsp;<code>Accept: application\/vnd.api+json;v=2.0<\/code>-style content negotiation. Additionally, these can be combined so the same application accepts multiple resolution strategies simultaneously.<\/p>\n<h3 class=\"wp-block-heading\">Built-in deprecation via RFC 9745 and RFC 8594<\/h3>\n<p>The part of Spring&#8217;s API versioning that will genuinely save operational pain is the built-in deprecation handling. The&nbsp;<code>StandardApiVersionDeprecationHandler<\/code>&nbsp;can automatically append&nbsp;<code>Deprecation<\/code>,&nbsp;<code>Sunset<\/code>, and&nbsp;<code>Link<\/code>&nbsp;headers to responses for deprecated versions \u2014 compliant with&nbsp;<a href=\"https:\/\/www.rfc-editor.org\/rfc\/rfc9745\" target=\"_blank\" rel=\"noreferrer noopener\">RFC 9745<\/a>&nbsp;and&nbsp;<a href=\"https:\/\/www.rfc-editor.org\/rfc\/rfc8594\" target=\"_blank\" rel=\"noreferrer noopener\">RFC 8594<\/a>. Before this, teams either implemented this manually in each controller or (more often) skipped it entirely and left clients with no signal that a version was being retired.<\/p>\n<pre class=\"brush:java\">\n@Override\npublic void configureApiVersioning(ApiVersionConfigurer configurer) {\n    StandardApiVersionDeprecationHandler handler =\n        new StandardApiVersionDeprecationHandler();\n\n    \/\/ v1.0 sunset date and link to migration docs\n    handler.addDeprecation(\"1.0\",\n        ZonedDateTime.of(2026, 9, 1, 0, 0, 0, 0, ZoneId.of(\"UTC\")),\n        URI.create(\"https:\/\/docs.example.com\/api\/migration\"));\n\n    configurer\n        .useRequestHeader(\"API-Version\")\n        .setVersionDeprecationHandler(handler);\n}\n\/\/ Response for v1.0 requests will now include:\n\/\/ Deprecation: @1735689600\n\/\/ Sunset: \"2026-09-01T00:00:00Z\"\n\/\/ Link: &lt;https:\/\/docs.example.com\/api\/migr\n<\/pre>\n<h2 class=\"wp-block-heading\" id=\"jspecify\">3. JSpecify: Null Safety That Finally Has Ecosystem Weight<\/h2>\n<p>Java&#8217;s null problem is old news. Tony Hoare called the null reference his &#8220;billion dollar mistake&#8221; in 2009. Java has had&nbsp;<code>Optional<\/code>&nbsp;since Java 8, and various null-annotation libraries for longer. The problem has never been lack of tools \u2014 it&#8217;s been fragmentation. JetBrains had their own&nbsp;<code>@Nullable<\/code>. Android had theirs. Spring had&nbsp;<code>org.springframework.lang.@Nullable<\/code>&nbsp;since 2017. JSR-305 stalled. No two tools agreed on semantics.<\/p>\n<p><a href=\"https:\/\/spring.io\/blog\/2025\/03\/10\/null-safety-in-spring-apps-with-jspecify-and-null-away\/\" target=\"_blank\" rel=\"noreferrer noopener\">JSpecify<\/a>&nbsp;is a Google-led collaborative effort \u2014 involving JetBrains, Oracle, Uber, Meta, Sonar, and Broadcom \u2014 to finally standardise nullability annotations. Version 1.0 shipped in July 2024. Spring Boot 4 adopts it portfolio-wide, deprecating Spring&#8217;s own&nbsp;<code>org.springframework.lang<\/code>&nbsp;annotations in its favour. IntelliJ IDEA 2025.3&nbsp;<a href=\"https:\/\/spring.io\/blog\/2025\/11\/12\/null-safe-applications-with-spring-boot-4\/\" target=\"_blank\" rel=\"noreferrer noopener\">ships first-class JSpecify support<\/a>, automatically preferring JSpecify annotations over JetBrains&#8217; own when both are on the classpath.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<h3 class=\"wp-block-heading\">How it actually works<\/h3>\n<p>JSpecify&#8217;s design is deliberately simple. Rather than annotating every non-null type (which would be the vast majority of your codebase), you declare a package as&nbsp;<code>@NullMarked<\/code>&nbsp;in a&nbsp;<code>package-info.java<\/code>&nbsp;file. Within that zone, everything is non-null by default. You annotate only the exceptions \u2014 the places where null is genuinely possible \u2014 with&nbsp;<code>@Nullable<\/code>.<\/p>\n<pre class=\"brush:java\">\n\/\/ src\/main\/java\/com\/example\/orders\/package-info.java\n@NullMarked\npackage com.example.orders;\nimport org.jspecify.annotations.NullMarked;\n\n\/\/ Within the @NullMarked package \u2014 everything is non-null by default\n@Service\npublic class OrderService {\n\n    \/\/ email is guaranteed non-null \u2014 no annotation needed\n    \/\/ promoCode explicitly allows null \u2014 @Nullable marks the exception\n    public Order createOrder(String email, @Nullable String promoCode) {\n        \/\/ IDE and NullAway will flag any unchecked use of promoCode\n        ...\n    }\n\n    \/\/ Return type explicitly nullable \u2014 caller must handle null\n    public @Nullable Order findByReference(String reference) {\n        return repository.findByRef(reference); \/\/ may return null\n    }\n\n    \/\/ Generic nullability \u2014 the List is non-null, but elements may be null\n    public List&lt;@Nullable String&gt; getSurveyResponses() { ... }\n}\n<\/pre>\n<p>The key difference from&nbsp;<code>Optional<\/code>: JSpecify is a static annotation, not a runtime wrapper. It carries zero runtime overhead. The nullability contract exists in the type system and is checked by tooling, not by the JVM.&nbsp;<code>Optional<\/code>&nbsp;is a runtime abstraction that wraps a value; nothing stops you from calling&nbsp;<code>.get()<\/code>&nbsp;without checking. JSpecify makes the contract visible to your IDE and, more importantly, to&nbsp;<a href=\"https:\/\/spring.io\/blog\/2025\/03\/10\/null-safety-in-spring-apps-with-jspecify-and-null-away\/\" target=\"_blank\" rel=\"noreferrer noopener\">NullAway<\/a>&nbsp;\u2014 an Error Prone plugin that turns annotation violations into build failures.<\/p>\n<p><strong>Compile-time enforcement with NullAway<\/strong><\/p>\n<p>IDE warnings are helpful but ignorable. NullAway, configured in your Gradle or Maven build, makes them not ignorable. When a&nbsp;<code>@Nullable<\/code>&nbsp;return value is used without a null check inside a&nbsp;<code>@NullMarked<\/code>&nbsp;package, NullAway fails the build. The error message is explicit:&nbsp;<code>[NullAway] dereferenced expression token is @Nullable<\/code>. JDK 17 users can use it with a JDK 21 toolchain; native support for JDK 17 compilation may follow. On Java 25,&nbsp;<code>-Xnullity<\/code>&nbsp;flag support is in discussion.<\/p>\n<h3 class=\"wp-block-heading\">What changes for your code<\/h3>\n<p>The practical impact depends entirely on how much you adopt. You can do nothing \u2014 JSpecify annotations in the Spring codebase are purely additive. Your code compiles and runs unchanged. The upside is that you immediately get better IDE null-flow analysis on Spring&#8217;s own APIs, because the framework code now carries explicit nullability contracts.<\/p>\n<p>If you want compile-time enforcement in your own code, the migration path is gradual by design. You add&nbsp;<code>@NullMarked<\/code>&nbsp;one package at a time. Any package without it behaves exactly as Java always has \u2014 unspecified nullability.&nbsp;<a href=\"https:\/\/marmo.dev\/spring-boot-4-null-safety\" target=\"_blank\" rel=\"noreferrer noopener\">As Marco Molteni&#8217;s detailed analysis notes<\/a>, the friction points are honest: on a large codebase, adding&nbsp;<code>@NullMarked<\/code>&nbsp;to a package can surface thousands of warnings at once.&nbsp;<code>@NullUnmarked<\/code>&nbsp;at the class or method level is the escape hatch for legacy code you can&#8217;t immediately fix \u2014 but it requires discipline to prevent it from becoming a permanent feature.<\/p>\n<figure class=\"wp-block-table\">\n<table class=\"has-fixed-layout\">\n<thead>\n<tr>\n<th class=\"has-text-align-left\" data-align=\"left\">Scenario<\/th>\n<th class=\"has-text-align-left\" data-align=\"left\">JSpecify benefit<\/th>\n<th class=\"has-text-align-left\" data-align=\"left\">Requires NullAway?<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Better IDE null-flow on Spring APIs<\/td>\n<td>Immediate, no config<\/td>\n<td>No \u2014 IntelliJ IDEA 2025.3 reads it automatically<\/td>\n<\/tr>\n<tr>\n<td>Your API contracts explicit for callers<\/td>\n<td>Add @NullMarked per package<\/td>\n<td>No \u2014 IDE warns; callers see the contract<\/td>\n<\/tr>\n<tr>\n<td>Build fails on null safety violations<\/td>\n<td>Full enforcement<\/td>\n<td>Yes \u2014 NullAway as an Error Prone annotation processor<\/td>\n<\/tr>\n<tr>\n<td>Kotlin integration<\/td>\n<td>Automatic<\/td>\n<td>No \u2014 Kotlin 2 translates JSpecify annotations to Kotlin nullability natively<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<h2 class=\"wp-block-heading\" id=\"jackson\">4. Jackson 3: The Breaking Change That Will Catch You Off Guard<\/h2>\n<p>Of the three changes this article covers, Jackson 3 is the one most likely to break your application silently. Not because the migration is technically complex \u2014&nbsp;<a href=\"https:\/\/spring.io\/blog\/2025\/10\/07\/introducing-jackson-3-support-in-spring\/\" target=\"_blank\" rel=\"noreferrer noopener\">most of it is mechanical<\/a>&nbsp;and automatable with OpenRewrite \u2014 but because two of its changed defaults will affect the shape of your JSON output without any compilation error to warn you first.<\/p>\n<h3 class=\"wp-block-heading\">The package and group ID rename<\/h3>\n<p>The most visible change is the package relocation. Every Jackson class that previously lived under&nbsp;<code>com.fasterxml.jackson<\/code>&nbsp;now lives under&nbsp;<code>tools.jackson<\/code>. The Maven group ID changes accordingly. The one intentional exception is&nbsp;<code>jackson-annotations<\/code>&nbsp;\u2014 annotations like&nbsp;<code>@JsonProperty<\/code>,&nbsp;<code>@JsonIgnore<\/code>, and&nbsp;<code>@JsonView<\/code>&nbsp;remain under&nbsp;<code>com.fasterxml.jackson.annotation<\/code>&nbsp;for backward compatibility and are shared between Jackson 2 and 3.<\/p>\n<p><em>Spring Boot 3 \u00b7 Jackson 2<\/em><\/p>\n<pre class=\"brush:java\">\n\/\/ pom.xml \/ build.gradle\ncom.fasterxml.jackson.core\n  :jackson-databind\n\n\/\/ Java import\nimport com.fasterxml.jackson\n  .databind.ObjectMapper;\n<\/pre>\n<p><em>Spring Boot 4 \u00b7 Jackson 3<\/em><\/p>\n<pre class=\"brush:java\">\n\/\/ pom.xml \/ build.gradle\ntools.jackson.core\n  :jackson-databind\n\n\/\/ Java import\nimport tools.jackson\n  .databind.json.JsonMapper;\n<\/pre>\n<p>Note the class rename too: the recommended entry point is now&nbsp;<code>JsonMapper<\/code>&nbsp;rather than&nbsp;<code>ObjectMapper<\/code>.&nbsp;<code>JsonMapper<\/code>&nbsp;extends&nbsp;<code>ObjectMapper<\/code>&nbsp;but offers an immutable builder API and comes pre-configured with sensible defaults for Java 17+ \u2014 you no longer need to register&nbsp;<code>jackson-datatype-jsr310<\/code>&nbsp;separately for&nbsp;<code>LocalDateTime<\/code>&nbsp;support. Spring Boot 4&#8217;s equivalent configuration hook is&nbsp;<code>JsonMapperBuilderCustomizer<\/code>, replacing&nbsp;<code>Jackson2ObjectMapperBuilderCustomizer<\/code>.<\/p>\n<h3 class=\"wp-block-heading\">The two default changes that will break your tests<\/h3>\n<p>These are the changes that require no import fix and generate no compile error, but will silently alter your JSON output the moment you upgrade:<\/p>\n<p><strong>Default 1: Dates are no longer timestamps<\/strong><\/p>\n<p>Jackson 2 default:&nbsp;<code>WRITE_DATES_AS_TIMESTAMPS = true<\/code>. Result:&nbsp;<code>{\"createdAt\": 1699257000000}<\/code><br \/>Jackson 3 default:&nbsp;<code>WRITE_DATES_AS_TIMESTAMPS = false<\/code>. Result:&nbsp;<code>{\"createdAt\": \"2025-11-06T05:30:00\"}<\/code><\/p>\n<p>ISO-8601 strings are more readable and easier for frontend frameworks to parse. But if your clients or tests assert on Unix timestamp format, they will fail silently in production after the upgrade. Audit every field of type&nbsp;<code>LocalDate<\/code>,&nbsp;<code>LocalDateTime<\/code>,&nbsp;<code>ZonedDateTime<\/code>,&nbsp;<code>Instant<\/code>, and&nbsp;<code>OffsetDateTime<\/code>&nbsp;in your API responses.<\/p>\n<p><strong>Default 2: Properties are sorted alphabetically<\/strong><\/p>\n<p>Jackson 2 default:&nbsp;<code>SORT_PROPERTIES_ALPHABETICALLY = false<\/code>&nbsp;(insertion order).<br \/>Jackson 3 default:&nbsp;<code>SORT_PROPERTIES_ALPHABETICALLY = true<\/code>.<\/p>\n<p>If your API clients parse JSON by field order, or if your snapshot tests assert on specific property ordering, they will start failing. JSON spec does not guarantee field order, so strict clients are technically wrong \u2014 but many exist in practice. OpenAPI-generated clients typically handle this correctly; bespoke parsing code sometimes does not.<\/p>\n<h3 class=\"wp-block-heading\">The exception change that will hit your catch blocks<\/h3>\n<p>Jackson 2&#8217;s&nbsp;<code>JsonProcessingException<\/code>&nbsp;extended&nbsp;<code>IOException<\/code>. Jackson 3&#8217;s&nbsp;<code>JacksonException<\/code>&nbsp;extends&nbsp;<code>RuntimeException<\/code>. Any&nbsp;<code>catch (IOException e)<\/code>&nbsp;block that was silently catching Jackson serialization errors will no longer catch them. The exception propagates unchecked. In production, this means a serialization failure that previously showed up as a handled error response now becomes an unhandled exception.<\/p>\n<pre class=\"brush:java\">\n\/\/ Spring Boot 3 \u2014 catch (IOException) also caught Jackson errors\ntry {\n    objectMapper.readValue(json, MyClass.class);\n} catch (IOException e) {  \/\/ &lt;- caught JsonProcessingException too\n    handleError(e);\n}\n\n\/\/ Spring Boot 4 \u2014 must catch JacksonException explicitly\ntry {\n    jsonMapper.readValue(json, MyClass.class);\n} catch (JacksonException e) {  \/\/ &lt;- unchecked, extends RuntimeException\n    handleError(e);\n}\n\/\/ Or catch both during a transition period:\n\/\/ } catch (IOException | JacksonException e) { ... }\n<\/pre>\n<h3 class=\"wp-block-heading\">The coexistence path<\/h3>\n<p>Spring Boot 4 ships with Jackson 2 compatibility support specifically to enable incremental migration. You can temporarily add&nbsp;<code>spring-boot-jackson2<\/code>&nbsp;instead of&nbsp;<code>spring-boot-starter-jackson<\/code>&nbsp;and use&nbsp;<code>spring.jackson.use-jackson2-defaults: true<\/code>&nbsp;in your configuration to preserve Jackson 2 behaviour while you migrate.&nbsp;<a href=\"https:\/\/spring.io\/blog\/2025\/10\/07\/introducing-jackson-3-support-in-spring\/\" target=\"_blank\" rel=\"noreferrer noopener\">The Spring team is explicit<\/a>&nbsp;that this is a bridge, not a long-term option: Jackson 2 auto-configuration is deprecated in Boot 4 and will be removed in a future release (expected 7.1 timeline).<\/p>\n<p class=\"has-text-align-center\"><strong>Spring Boot 4 Migration Effort by Change Area<\/strong><\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2026\/04\/2026-04-03_21-35-31.png\"><img decoding=\"async\" width=\"559\" height=\"269\" src=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2026\/04\/2026-04-03_21-35-31.png\" alt=\"\" class=\"wp-image-142558\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2026\/04\/2026-04-03_21-35-31.png 559w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2026\/04\/2026-04-03_21-35-31-300x144.png 300w\" sizes=\"(max-width: 559px) 100vw, 559px\" \/><\/a><figcaption class=\"wp-element-caption\">Qualitative assessment \u2014 higher bar = more migration effort required. Based on community migration reports, Spring migration guide, OpenRewrite coverage<\/figcaption><\/figure>\n<\/div>\n<h2 class=\"wp-block-heading\" id=\"migration\">5. Migration Reality: What to Do Before Upgrading<\/h2>\n<p>A practical checklist, not a complete migration guide (use the&nbsp;<a href=\"https:\/\/github.com\/spring-projects\/spring-boot\/wiki\/Spring-Boot-4.0-Migration-Guide\" target=\"_blank\" rel=\"noreferrer noopener\">official one<\/a>&nbsp;for that):<\/p>\n<figure class=\"wp-block-table\">\n<table class=\"has-fixed-layout\">\n<thead>\n<tr>\n<th class=\"has-text-align-left\" data-align=\"left\">Task<\/th>\n<th class=\"has-text-align-left\" data-align=\"left\">Priority<\/th>\n<th class=\"has-text-align-left\" data-align=\"left\">Tool<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>Upgrade to Spring Boot 3.5 and fix all deprecation warnings<\/strong><\/td>\n<td>Must do first<\/td>\n<td>IDE inspection,&nbsp;<code>mvn dependency:tree<\/code><\/td>\n<\/tr>\n<tr>\n<td><strong>Remove remaining&nbsp;<code>javax.*<\/code>&nbsp;imports<\/strong><\/td>\n<td>Required<\/td>\n<td>OpenRewrite&nbsp;<code>Migrate_To_Jakarta_EE_10<\/code><\/td>\n<\/tr>\n<tr>\n<td><strong>Migrate Jackson imports<\/strong>&nbsp;from&nbsp;<code>com.fasterxml.jackson<\/code>&nbsp;to&nbsp;<code>tools.jackson<\/code><\/td>\n<td>Required<\/td>\n<td>OpenRewrite&nbsp;<code>UpgradeJackson_2_3<\/code><\/td>\n<\/tr>\n<tr>\n<td><strong>Audit date\/time serialization<\/strong>&nbsp;\u2014 add&nbsp;<code>WRITE_DATES_AS_TIMESTAMPS=true<\/code>&nbsp;to preserve old behaviour, or update clients<\/td>\n<td>Sneaky \u2014 no compile error<\/td>\n<td>JSON snapshot tests, Postman contract tests<\/td>\n<\/tr>\n<tr>\n<td><strong>Audit property ordering<\/strong>&nbsp;\u2014 add&nbsp;<code>SORT_PROPERTIES_ALPHABETICALLY=false<\/code>&nbsp;or update contract tests<\/td>\n<td>Check your tests<\/td>\n<td>Snapshot diff on API responses<\/td>\n<\/tr>\n<tr>\n<td><strong>Update catch blocks<\/strong>&nbsp;from&nbsp;<code>IOException<\/code>&nbsp;to&nbsp;<code>JacksonException<\/code><\/td>\n<td>Required<\/td>\n<td>IDE search for&nbsp;<code>catch (IOException<\/code>&nbsp;near Jackson calls<\/td>\n<\/tr>\n<tr>\n<td><strong>Rename starters<\/strong>&nbsp;(<code>spring-boot-starter-webmvc<\/code>&nbsp;replaces&nbsp;<code>spring-boot-starter-web<\/code>)<\/td>\n<td>Or use classic bridge<\/td>\n<td>Spring Boot Migration Guide starter table<\/td>\n<\/tr>\n<tr>\n<td><strong>Add JSpecify dependency and&nbsp;<code>@NullMarked<\/code><\/strong>&nbsp;to new packages<\/td>\n<td>Optional \u2014 additive<\/td>\n<td>IntelliJ IDEA 2025.3, NullAway (optional)<\/td>\n<\/tr>\n<tr>\n<td><strong>Configure API versioning<\/strong>&nbsp;in&nbsp;<code>WebMvcConfigurer<\/code><\/td>\n<td>Optional \u2014 new feature<\/td>\n<td>Spring Framework 7 docs,&nbsp;<code>ApiVersionConfigurer<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p><strong>OpenRewrite covers most of the mechanical work<\/strong><\/p>\n<p>The OpenRewrite recipe&nbsp;<code>org.openrewrite.java.jackson.UpgradeJackson_2_3<\/code>&nbsp;handles the Jackson package and group ID migration automatically. The recipe&nbsp;<code>Migrate_To_Jakarta_EE_10<\/code>&nbsp;handles remaining&nbsp;<code>javax.*<\/code>&nbsp;imports. What OpenRewrite cannot do: catch the date serialization default change, find&nbsp;<code>catch (IOException)<\/code>&nbsp;blocks that silently swallowed Jackson errors, or reason about client contract expectations. Those require manual review.<\/p>\n<h2 class=\"wp-block-heading\">6. What We Have Learned<\/h2>\n<p>Spring Boot 4 is not a routine major version bump. The three changes covered here are each genuinely structural: API versioning becomes a first-class framework concept rather than a convention bolted onto&nbsp;<code>@RequestMapping<\/code>. JSpecify gives Java a standardised null contract specification with the ecosystem weight to finally matter \u2014 the Spring team, JetBrains, Google, Uber, and Oracle all behind the same annotations is different from the previous fragmented landscape. Jackson 3 changes the JSON library your application uses at its foundation.<\/p>\n<p>Of the three, Jackson 3 is the most likely to cause production incidents on teams that don&#8217;t read the fine print. The package rename is mechanical and OpenRewrite handles it. The date serialization default and property ordering default are silent \u2014 no compiler warning, no deprecation notice. They change the shape of your JSON output. Clients that parse Unix timestamps or depend on field ordering will break. Find them in your contract tests before they find themselves in production.<\/p>\n<p>JSpecify is the most underrated change. The fragmentation of null annotation libraries in Java has been a real cost \u2014 tools that don&#8217;t interoperate, conventions that differ per library, and IDE support that varies by which annotation you chose. Having the Spring portfolio, Kotlin&#8217;s nullability system, and IntelliJ IDEA&#8217;s flow analysis all reading from the same specification is a meaningful baseline improvement even if you never write a single&nbsp;<code>@NullMarked<\/code>&nbsp;annotation yourself. If you do adopt it, start package by package and treat&nbsp;<code>@NullUnmarked<\/code>&nbsp;as a temporary escape hatch with a deadline, not a permanent exception.<\/p>\n<p>And API versioning \u2014 if you&#8217;ve been putting this off because every solution felt like a hack on top of Spring rather than a feature of it, that excuse is now gone. The&nbsp;<code>version<\/code>&nbsp;attribute on mapping annotations, the&nbsp;<code>StandardApiVersionDeprecationHandler<\/code>&nbsp;for RFC-compliant sunset headers, and&nbsp;<code>ApiVersionInserter<\/code>&nbsp;for clients add up to a versioning system you can actually maintain. The right time to design it into a new service is before version 2 exists, not after.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The migration guides list dozens of changes. Most articles rehash the changelog. This piece focuses on the three changes that will meaningfully alter how you design APIs in 2026: built-in API versioning, null-safe annotations from JSpecify, and Jackson 3 defaults that will silently break your serialization tests. 1. What This Release Actually Is Spring Boot &hellip;<\/p>\n","protected":false},"author":1010,"featured_media":240,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[2845,1200,854],"class_list":["post-142557","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-api-design","tag-java","tag-spring-boot"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Spring Boot 4 vs. 3: What Actually Changed - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"Spring Boot 4 and Spring Framework 7 went GA in November 2025. Most articles rehash the changelog. This one focuses on the three changes\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2026\/04\/spring-boot-4-vs-3-what-actually-changed.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Spring Boot 4 vs. 3: What Actually Changed - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"Spring Boot 4 and Spring Framework 7 went GA in November 2025. Most articles rehash the changelog. This one focuses on the three changes\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2026\/04\/spring-boot-4-vs-3-what-actually-changed.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2026-04-08T06:28:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Eleftheria Drosopoulou\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Eleftheria Drosopoulou\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2026\\\/04\\\/spring-boot-4-vs-3-what-actually-changed.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2026\\\/04\\\/spring-boot-4-vs-3-what-actually-changed.html\"},\"author\":{\"name\":\"Eleftheria Drosopoulou\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/5fe56fff01ece0694747967c7217bca4\"},\"headline\":\"Spring Boot 4 vs. 3: What Actually Changed\",\"datePublished\":\"2026-04-08T06:28:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2026\\\/04\\\/spring-boot-4-vs-3-what-actually-changed.html\"},\"wordCount\":2195,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2026\\\/04\\\/spring-boot-4-vs-3-what-actually-changed.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"keywords\":[\"API Design\",\"Java\",\"Spring Boot\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2026\\\/04\\\/spring-boot-4-vs-3-what-actually-changed.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2026\\\/04\\\/spring-boot-4-vs-3-what-actually-changed.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2026\\\/04\\\/spring-boot-4-vs-3-what-actually-changed.html\",\"name\":\"Spring Boot 4 vs. 3: What Actually Changed - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2026\\\/04\\\/spring-boot-4-vs-3-what-actually-changed.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2026\\\/04\\\/spring-boot-4-vs-3-what-actually-changed.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"datePublished\":\"2026-04-08T06:28:00+00:00\",\"description\":\"Spring Boot 4 and Spring Framework 7 went GA in November 2025. Most articles rehash the changelog. This one focuses on the three changes\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2026\\\/04\\\/spring-boot-4-vs-3-what-actually-changed.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2026\\\/04\\\/spring-boot-4-vs-3-what-actually-changed.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2026\\\/04\\\/spring-boot-4-vs-3-what-actually-changed.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"width\":150,\"height\":150,\"caption\":\"spring-interview-questions-answers\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2026\\\/04\\\/spring-boot-4-vs-3-what-actually-changed.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Spring Boot 4 vs. 3: What Actually Changed\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/5fe56fff01ece0694747967c7217bca4\",\"name\":\"Eleftheria Drosopoulou\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2015\\\/03\\\/Eleftheria-Drosopoulou-96x96.jpg\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2015\\\/03\\\/Eleftheria-Drosopoulou-96x96.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2015\\\/03\\\/Eleftheria-Drosopoulou-96x96.jpg\",\"caption\":\"Eleftheria Drosopoulou\"},\"description\":\"Eleftheria is an Experienced Business Analyst with a robust background in the computer software industry. Proficient in Computer Software Training, Digital Marketing, HTML Scripting, and Microsoft Office, they bring a wealth of technical skills to the table. Additionally, she has a love for writing articles on various tech subjects, showcasing a talent for translating complex concepts into accessible content.\",\"sameAs\":[\"http:\\\/\\\/www.javacodegeeks.com\\\/\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/eleftheria-drosopoulou\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Spring Boot 4 vs. 3: What Actually Changed - Java Code Geeks","description":"Spring Boot 4 and Spring Framework 7 went GA in November 2025. Most articles rehash the changelog. This one focuses on the three changes","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2026\/04\/spring-boot-4-vs-3-what-actually-changed.html","og_locale":"en_US","og_type":"article","og_title":"Spring Boot 4 vs. 3: What Actually Changed - Java Code Geeks","og_description":"Spring Boot 4 and Spring Framework 7 went GA in November 2025. Most articles rehash the changelog. This one focuses on the three changes","og_url":"https:\/\/www.javacodegeeks.com\/2026\/04\/spring-boot-4-vs-3-what-actually-changed.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2026-04-08T06:28:00+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","type":"image\/jpeg"}],"author":"Eleftheria Drosopoulou","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Eleftheria Drosopoulou","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2026\/04\/spring-boot-4-vs-3-what-actually-changed.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2026\/04\/spring-boot-4-vs-3-what-actually-changed.html"},"author":{"name":"Eleftheria Drosopoulou","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/5fe56fff01ece0694747967c7217bca4"},"headline":"Spring Boot 4 vs. 3: What Actually Changed","datePublished":"2026-04-08T06:28:00+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2026\/04\/spring-boot-4-vs-3-what-actually-changed.html"},"wordCount":2195,"commentCount":0,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2026\/04\/spring-boot-4-vs-3-what-actually-changed.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","keywords":["API Design","Java","Spring Boot"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2026\/04\/spring-boot-4-vs-3-what-actually-changed.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2026\/04\/spring-boot-4-vs-3-what-actually-changed.html","url":"https:\/\/www.javacodegeeks.com\/2026\/04\/spring-boot-4-vs-3-what-actually-changed.html","name":"Spring Boot 4 vs. 3: What Actually Changed - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2026\/04\/spring-boot-4-vs-3-what-actually-changed.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2026\/04\/spring-boot-4-vs-3-what-actually-changed.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","datePublished":"2026-04-08T06:28:00+00:00","description":"Spring Boot 4 and Spring Framework 7 went GA in November 2025. Most articles rehash the changelog. This one focuses on the three changes","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2026\/04\/spring-boot-4-vs-3-what-actually-changed.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2026\/04\/spring-boot-4-vs-3-what-actually-changed.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2026\/04\/spring-boot-4-vs-3-what-actually-changed.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","width":150,"height":150,"caption":"spring-interview-questions-answers"},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2026\/04\/spring-boot-4-vs-3-what-actually-changed.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"Spring Boot 4 vs. 3: What Actually Changed"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/5fe56fff01ece0694747967c7217bca4","name":"Eleftheria Drosopoulou","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2015\/03\/Eleftheria-Drosopoulou-96x96.jpg","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2015\/03\/Eleftheria-Drosopoulou-96x96.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2015\/03\/Eleftheria-Drosopoulou-96x96.jpg","caption":"Eleftheria Drosopoulou"},"description":"Eleftheria is an Experienced Business Analyst with a robust background in the computer software industry. Proficient in Computer Software Training, Digital Marketing, HTML Scripting, and Microsoft Office, they bring a wealth of technical skills to the table. Additionally, she has a love for writing articles on various tech subjects, showcasing a talent for translating complex concepts into accessible content.","sameAs":["http:\/\/www.javacodegeeks.com\/"],"url":"https:\/\/www.javacodegeeks.com\/author\/eleftheria-drosopoulou"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/142557","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/1010"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=142557"}],"version-history":[{"count":1,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/142557\/revisions"}],"predecessor-version":[{"id":142559,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/142557\/revisions\/142559"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/240"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=142557"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=142557"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=142557"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}