Technology1 min read

Port Your Spring Code With Fewer Edits, and Libraries That Bring Their Own Server

By · Published by Everything Blog

In short

Developers can now transition Spring services to native executables primarily by repointing package imports to Codename One. The platform natively incorporates essential controller features like CORS, standard logging, and compile-time JSON serialization that avoids runtime reflection. Additionally, the backend expands core JDK support to include types like BigDecimal, regular expressions, and local dates. Security and data layers are also upgraded with persistent logins, large object mappings, and a SHA-256 encoder for legacy credentials.

Key points

  • Migrating Spring controllers to native binaries now primarily requires redirecting packag…: Migrating Spring controllers to native binaries now primarily requires redirecting package imports to Codename One.
  • Built-in controller capabilities now encompass cross-origin resource sharing, header vali…: Built-in controller capabilities now encompass cross-origin resource sharing, header validation, and HTTP response exception handling.
  • Legacy user databases can transition smoothly without password resets by utilizing the ne…: Legacy user databases can transition smoothly without password resets by utilizing the new SHA-256 password encoder.

Sources checked by our analysis pipeline: 1

The Codename One backend compiles your server to a native executable that starts in 40 ms and idles in about 9 MB. The catch has always been porting: real Spring services lean on dozens of small conveniences, and every one that’s missing is an edit. This round we took real services across and fixed what they tripped on, so most of this post is code that now moves over with nothing but its imports changed.

A Spring controller, mostly unchanged

Here’s a typical order endpoint. Every line of the body works on the backend now:

@RestController

@CrossOrigin(origins = "https://shop.example.com", allowCredentials = true)

public class OrderController {

private static final Logger LOG = Logger.getLogger(OrderController.class);

@Autowired

private OrderRepository orders;

@PostMapping(value = "/orders", consumes = "application/json", produces = "application/json")

public Order place(@RequestBody Order order) {

if (order.lines.isEmpty()) {

throw new ResponseStatusException(400, "An order needs at least one line");

}

MDC.put("customer", order.customer);

try {

LOG.info("Placing order with {} lines", order.lines.size());

return orders.save(order);

} finally {

MDC.remove("customer");

}

}

}

What changed to make that work:

consumes

andproduces

are checked. A request with the wrongContent-Type

Technology