|
| 1 | +## Migrating from javax to jakarta for Spring Boot 3 |
| 2 | + |
| 3 | +The Java community is going through its Python2 → Python3 moment. |
| 4 | +Oracle donated source code to open source, but their lawyers said that the Java trademark must be protected. |
| 5 | +Therefore, the donated code must be repackaged from *javax* to *jakarta* (e.g. from *javax.servlet* to *jakarta.servlet*). |
| 6 | +The Maven GAVs change too (e.g. *javax.servlet:javax.servlet-api* to *jakarta.servlet:jakarta.servlet-api*). |
| 7 | +Read more [in this article](https://blogs.oracle.com/javamagazine/post/transition-from-java-ee-to-jakarta-ee). |
| 8 | + |
| 9 | +This is obviously super disruptive. |
| 10 | +These changes affect runtime, not just compile time. |
| 11 | +If you have a compiled jar file with code that references a class in the *javax.servlet* package, |
| 12 | + it will break at runtime if you deploy it with the newly packaged *jakarta* servlet jar. |
| 13 | +Therefore you have to make the switch across many libs, all at once. |
| 14 | +This is a big bang upgrade, folks. |
| 15 | + |
| 16 | +The Spring Boot project chose to force this migration with [Spring Boot 3](https://spring.io/blog/2022/11/24/spring-boot-3-0-goes-ga). |
| 17 | +Whether you like it or not, you must migrate to stay on a supported version of Spring Boot. |
| 18 | +Good times. |
| 19 | + |
| 20 | +### Jakarta Migration Path (in a nutshell) |
| 21 | + |
| 22 | +There is a migration path for going from *javax* to *jakarta*. |
| 23 | +It doesn't make it easy, but it does allow you to break it up a little. |
| 24 | + |
| 25 | +The important thing to know is that there are two aspects of migration: the **GAV**, and the **Java package**. |
| 26 | +- the GAV migration (groupId, artifactId, version) moves from a *javax* groupId and artifactId, to a *jakarta* one |
| 27 | +- the Java package migration involves moving from classes in a *javax* package, to a *jakarta* package |
| 28 | + |
| 29 | +The GAV migration is the easier one, since it is just a configuration change. |
| 30 | +The Java package migration is tough, because it involves actual code level changes to use the migrated package names. |
| 31 | + |
| 32 | +### Transitional Jars |
| 33 | + |
| 34 | +The Jakarta team helps you out a little bit by providing what I call *transitional jars*. |
| 35 | +These jars are half migrated jars that allow you to take the migration steps incrementally. |
| 36 | +The best way to explain them is to provide an example: |
| 37 | + |
| 38 | +- Javax Jar: |
| 39 | + - GAV: *javax.json:javax.json-api:1.1.4* Java package: *javax.json* |
| 40 | +- Transition Jar: |
| 41 | + - GAV: *jakarta.json:jakarta.json-api:1.1.6* Java package: *javax.json* |
| 42 | +- Jakarta Jar: |
| 43 | + - GAV: *jakarta.json:jakarta.json-api:2.1.2* Java package: *jakarta.json* |
| 44 | + |
| 45 | +This allows you to update to an early version of the *jakarta* GAV, without adopting the Java package change too. |
| 46 | +After upgrading to the transitional jars, you should enable the |
| 47 | +[springboot rule duplicate class check](https://github.com/salesforce/rules_spring/blob/main/springboot/unwanted_classes.md#detecting-duplicate-classes) |
| 48 | + which should highlight any jars bringing in old versions of the migrating *javax* classes. |
| 49 | + |
| 50 | +### Javax Detect Mode |
| 51 | + |
| 52 | +After upgrading to the transitional jars, and enabling the duplicate class checker, you need to continue to look for *javax* classes |
| 53 | + in your classpath that are not in a transitional jar. |
| 54 | +There are widely used projects out there that did bad things - they included standard *javax* classes in their jar files. |
| 55 | +While those projects **might** continue to function properly on old *javax* classes, they need to be researched. |
| 56 | +They hopefully have newer versions that use the newer *jakarta* classes. |
| 57 | + |
| 58 | +The springboot rule has a *javaxdetect* mode to help with this. |
| 59 | +When enabled, it will detect classes in the classpath located in a _javax.*_ package. |
| 60 | +If the jar that contains that class is not in your ignorelist, the build will fail. |
| 61 | +The intent is for you to analyze all *javax* classes in your classpath to determine if/when/how they will migrate to _jakarta_. |
| 62 | + |
| 63 | +Example: |
| 64 | + |
| 65 | +```starlark |
| 66 | +springboot( |
| 67 | + name = "my-boot-app", |
| 68 | + boot_app_class = "com.acme.MyService", |
| 69 | + javaxdetect_enable = True, |
| 70 | + javaxdetect_ignorelist = "//tools/springboot:javaxdetect_ignorelist.txt", |
| 71 | + java_library = ":base_lib", |
| 72 | +) |
| 73 | +``` |
| 74 | + |
| 75 | +where the contents of the *javaxdetect_ignorelist.txt* file is: |
| 76 | + |
| 77 | +``` |
| 78 | +# these are transitional jars, these are ok: |
| 79 | +jakarta.activation-api-1.2.2.jar |
| 80 | +jakarta.annotation-api-1.3.5.jar |
| 81 | +jakarta.el-3.0.4.jar |
| 82 | +jakarta.inject-api-1.0.5.jar |
| 83 | +jakarta.interceptor-api-1.2.5.jar |
| 84 | +jakarta.json-api-1.1.6.jar |
| 85 | +jakarta.persistence-api-2.2.3.jar |
| 86 | +jakarta.servlet-api-4.0.4.jar |
| 87 | +jakarta.transaction-api-1.3.3.jar |
| 88 | +jakarta.validation-api-2.0.2.jar |
| 89 | +jakarta.ws.rs-api-2.1.6.jar |
| 90 | +jakarta.xml.bind-api-2.3.3.jar |
| 91 | +
|
| 92 | +# TODO: what is going on here, why do these jars have javax classes in them? |
| 93 | +# Within salesforce, we have a bunch of these, each needs to be researched. |
| 94 | +# You might be SURPRISED to see how many projects do dumb things, like embedding |
| 95 | +# standard javax classes in their own jars. |
| 96 | +abc-1.0.0.jar |
| 97 | +def-2.0.0.jar |
| 98 | +ghi-3.0.0.jar |
| 99 | +``` |
| 100 | + |
| 101 | +For completeness, this is the BUILD file at *//tools/springboot*: |
| 102 | + |
| 103 | +``` |
| 104 | +exports_files([ |
| 105 | + "javaxdetect_ignorelist.txt", |
| 106 | +]) |
| 107 | +``` |
| 108 | + |
| 109 | +### Javax Reference Checking |
| 110 | + |
| 111 | +Ideally the *springboot()* rule would have a feature for *javax* reference checking. |
| 112 | +Meaning, it would decompile every class in the springboot classpath and check if any were referencing |
| 113 | + a *javax* package. |
| 114 | +We don't have that. I wish we did. |
| 115 | + |
| 116 | +### Finishing the Jakarta Migration |
| 117 | + |
| 118 | +Once you have moved to the transitional jars, and have identified jars with javax classes in them, you will be ready |
| 119 | + to finish your migration. |
| 120 | +You need to move from the transitional GAV, to the jakarta GAV. |
| 121 | +This must happen at the same time as upgrading: |
| 122 | +- Spring Boot 3 |
| 123 | +- Spring 6 |
| 124 | +- Jetty 11 |
| 125 | +- and others |
| 126 | + |
| 127 | +It is going to be fun. |
0 commit comments