🔸 TLDR
▪️ JAX-RS (Jakarta REST) lets you build clean REST APIs with annotations (@Path, @GET, @POST…), consume them with a typed client API, handle query/path params safely, and even stream updates with Server-Sent Events (SSE). 🚀

🔸 SIMPLE RESTFUL WEB SERVICE
▪️ Define a resource with @Path + HTTP method annotations
▪️ Configure the application entry point with @ApplicationPath
▪️ Serialize/deserialize data (Java ↔ XML) with JAXB (and often JSON too)
▪️ Test quickly with curl / Postman / integration tests ✅
import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; @Path("/hello") @Produces(MediaType.TEXT_PLAIN) public class HelloResource { @GET public String hello(@QueryParam("name") @DefaultValue("world") String name) { return "Hello " + name; } } import jakarta.ws.rs.ApplicationPath; import jakarta.ws.rs.core.Application; @ApplicationPath("/api") public class RestApp extends Application { // empty is fine: auto-discovery by container }
✅ Quick test:
curl "http://localhost:8080/myapp/api/hello?name=Vincent"
🔸 CONVERTING DATA BETWEEN JAVA AND XML WITH JAXB
▪️ JAXB uses annotations like @XmlRootElement to map Java objects to XML : https://jakarta.ee/specifications/xml-binding/2.3/apidocs/javax/xml/bind/annotation/xmlrootelement
▪️ Works great for legacy integrations & enterprise APIs 🏢
import jakarta.xml.bind.annotation.*; @XmlRootElement(name = "user") @XmlAccessorType(XmlAccessType.FIELD) public class User { public Long id; public String name; public User() {} public User(Long id, String name) { this.id = id; this.name = name; } } import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; @Path("/users") @Produces(MediaType.APPLICATION_XML) @Consumes(MediaType.APPLICATION_XML) public class UserResource { @GET @Path("/{id}") public User get(@PathParam("id") long id) { return new User(id, "Ada"); } }
🔸 RESTFUL WEB SERVICE CLIENT (JAX-RS CLIENT API)
▪️ Use ClientBuilder + WebTarget to call APIs
▪️ You can send headers, JSON/XML bodies, handle status codes, etc. 🧰
import jakarta.ws.rs.client.*; import jakarta.ws.rs.core.MediaType; Client client = ClientBuilder.newClient(); String txt = client .target("http://localhost:8080/myapp/api/hello") .queryParam("name", "Vincent") .request(MediaType.TEXT_PLAIN) .get(String.class); System.out.println(txt);
🔸 QUERY & PATH PARAMETERS
▪️ Server side: @QueryParam, @PathParam, @DefaultValue
▪️ Client side: queryParam() and resolveTemplate() (safe path replacement) 🔒
Server
@Path("/orders") public class OrderResource { @GET @Path("/{id}") @Produces(MediaType.APPLICATION_JSON) public String getOrder( @PathParam("id") String id, @QueryParam("verbose") @DefaultValue("false") boolean verbose ) { return "{\"id\":\"" + id + "\",\"verbose\":" + verbose + "}"; } }
Client
import jakarta.ws.rs.client.*; import jakarta.ws.rs.core.MediaType; Client client = ClientBuilder.newClient(); String json = client .target("http://localhost:8080/myapp/api") .path("/orders/{id}") .resolveTemplate("id", "A-42") .queryParam("verbose", true) .request(MediaType.APPLICATION_JSON) .get(String.class); System.out.println(json);
🔸 SERVER-SENT EVENTS (SSE)
▪️ SSE = one-way stream from server ➜ client over HTTP (perfect for live updates) 📡
▪️ Great for dashboards, notifications, progress updates… without WebSockets.
Server (push events)
import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.sse.*; @Path("/stream") public class SseResource { @GET @Produces(MediaType.SERVER_SENT_EVENTS) public void stream(@Context SseEventSink sink, @Context Sse sse) { for (int i = 1; i <= 5; i++) { OutboundSseEvent event = sse.newEventBuilder() .name("tick") .data(String.class, "event #" + i) .build(); sink.send(event); } sink.close(); } }
Client (listen to events)
import jakarta.ws.rs.client.*; import jakarta.ws.rs.sse.*; Client client = ClientBuilder.newBuilder().build(); WebTarget target = client.target("http://localhost:8080/myapp/api/stream"); try (SseEventSource source = SseEventSource.target(target).build()) { source.register( (InboundSseEvent e) -> System.out.println("SSE: " + e.readData()), (Throwable t) -> t.printStackTrace(), () -> System.out.println("SSE closed") ); source.open(); Thread.sleep(2000); // demo wait }
🔸 TAKEAWAYS
▪️ JAX-RS keeps REST code tiny + readable with annotations ✨
▪️ JAXB makes XML interop painless for enterprise/legacy needs 🧾
▪️ The JAX-RS client API gives you a first-class way to call services 🔁
▪️ Query + path params are safe & explicit (less string concatenation!) ✅
▪️ SSE is the simplest “real-time-ish” option when you only need server ➜ client 📣
#Java #JakartaEE #JAXRS #REST #Backend #APIs #Microservices #SSE #JAXB #WebDevelopment #SoftwareEngineering
Go further with Java certification:
Java👇
Spring👇
SpringBook👇
JavaBook👇