juneau-shaded-rest-server
The juneau-shaded-rest-server artifact bundles all core Juneau modules plus REST server functionality. At 3.8 MB, it provides everything needed for building REST server applications.
What's Included
This artifact includes:
- All modules from juneau-shaded-core (marshalling, config, testing)
- juneau-rest-common - REST APIs common to client and server
- juneau-rest-server - Full-featured REST servlet API
- juneau-rest-server-rdf - RDF support for REST servers
- juneau-rest-mock - REST testing utilities
Use Cases
Use juneau-shaded-rest-server when you need:
- REST API development - Create RESTful web services
- Servlet-based applications - Deploy to any Servlet 6.1+ container
- Automatic content negotiation - Support multiple formats automatically
- Swagger/OpenAPI integration - Built-in API documentation
- Testing REST services - Use the mock framework
Maven Dependency
<dependency>
<groupId>org.apache.juneau</groupId>
<artifactId>juneau-shaded-rest-server</artifactId>
<version>${juneau.version}</version>
</dependency>
Bazel Dependency
maven_jar(
name = "juneau_rest_server",
artifact = "org.apache.juneau:juneau-shaded-rest-server:${juneau.version}",
)
# External dependencies
maven_jar(
name = "jakarta_servlet_api",
artifact = "jakarta.servlet:jakarta.servlet-api:6.1.0",
)
maven_jar(
name = "jetty_server",
artifact = "org.eclipse.jetty:jetty-server:12.0.5",
)
java_library(
name = "my_rest_api",
srcs = glob(["src/**/*.java"]),
deps = [
"@juneau_rest_server//jar",
"@jakarta_servlet_api//jar",
"@jetty_server//jar",
],
)
External Dependencies
juneau-shaded-rest-server requires:
Required
- Jakarta Servlet API 6.1+ - Servlet specification
Optional
- Jakarta XML Bind API 3.0+ - For XML serialization
- Apache Jena - For RDF support
- Servlet Container - Jetty, Tomcat, etc. (runtime dependency)
Example Usage
Basic REST Resource
import org.apache.juneau.rest.annotation.*;
import org.apache.juneau.rest.servlet.*;
@Rest(
path="/petstore",
title="Petstore API",
description="Sample REST API"
)
public class PetStoreResource extends BasicRestServlet {
@RestGet(path="/pets")
public List<Pet> getPets() {
return petService.getAllPets();
}
@RestGet(path="/pets/{id}")
public Pet getPet(@Path int id) {
return petService.getPet(id);
}
@RestPost(path="/pets")
public Pet createPet(@Content Pet pet) {
return petService.createPet(pet);
}
@RestPut(path="/pets/{id}")
public Pet updatePet(@Path int id, @Content Pet pet) {
return petService.updatePet(id, pet);
}
@RestDelete(path="/pets/{id}")
public void deletePet(@Path int id) {
petService.deletePet(id);
}
}
Automatic Content Negotiation
Juneau automatically serializes responses based on the Accept header:
@RestGet(path="/person/{id}")
public Person getPerson(@Path int id) {
return new Person("John Smith", 42);
}
// GET /person/1
// Accept: application/json → {"name":"John Smith","age":42}
// Accept: text/xml → <object><name>John Smith</name><age>42</age></object>
// Accept: text/html → <table>...</table>
// Accept: text/plain → name=John Smith, age=42
Request Body Parsing
@RestPost(path="/person")
public Person createPerson(@Content Person person) {
// person is automatically parsed from JSON, XML, etc.
return personService.create(person);
}
// POST /person
// Content-Type: application/json
// Body: {"name":"John","age":42}
Path Parameters
@RestGet(path="/users/{userId}/posts/{postId}")
public Post getUserPost(
@Path("userId") int userId,
@Path("postId") int postId
) {
return postService.getPost(userId, postId);
}
Query Parameters
@RestGet(path="/search")
public List<Result> search(
@Query("q") String query,
@Query("limit") @Default("10") int limit,
@Query("offset") @Default("0") int offset
) {
return searchService.search(query, limit, offset);
}
// GET /search?q=juneau&limit=20&offset=40
Request/Response Headers
@RestGet(path="/data")
public String getData(
@Header("User-Agent") String userAgent,
RestResponse res
) {
res.setHeader("X-Custom", "value");
return "data";
}
Swagger/OpenAPI Integration
@Rest(
path="/api",
swagger=@Swagger(
title="My API",
version="1.0",
description="API Description",
contact=@Contact(name="Support", email="support@example.com")
)
)
public class MyApi extends BasicRestServlet {
@RestGet(
path="/items",
summary="Get all items",
description="Returns a list of all items"
)
public List<Item> getItems() {
return itemService.getAll();
}
}
// Swagger UI available at: /api/swagger
// OpenAPI JSON at: /api/openapi.json
Exception Handling
@RestGet(path="/person/{id}")
public Person getPerson(@Path int id) throws NotFound {
Person person = personService.getPerson(id);
if (person == null)
throw new NotFound("Person not found: {0}", id);
return person;
}
// Returns HTTP 404 with error message
Guards and Matchers
@Rest(path="/admin")
@RestGuard(AdminGuard.class) // Require admin role
public class AdminResource extends BasicRestServlet {
@RestGet(path="/users")
public List<User> getUsers() {
return userService.getAllUsers();
}
}
public class AdminGuard extends RestGuard {
@Override
public boolean guard(RestRequest req, RestResponse res) {
return req.isUserInRole("admin");
}
}
Converters
@Rest(
path="/api",
converters={Queryable.class, Introspectable.class}
)
public class MyApi extends BasicRestServlet {
@RestGet(path="/people")
public List<Person> getPeople() {
return personService.getAll();
}
// GET /people?s=age>21&v=name,age&o=age
// Returns filtered, sorted, and projected results
}
Configuration
@Rest(
path="/api",
config="myapi.cfg", // External config file
defaultAccept="application/json",
defaultContentType="application/json",
maxInput="10M" // Limit request size
)
public class MyApi extends BasicRestServlet {
// ...
}
Features
Built-in Serializers/Parsers
- JSON (multiple flavors)
- XML
- HTML (with customizable styling)
- URL-Encoding
- MessagePack
- OpenAPI
- Plain Text
- CSV
Automatic Features
- Content negotiation
- Character encoding detection
- GZIP compression
- Request/response logging
- Exception mapping
- Bean validation
Advanced Features
- Role-based security
- Method-level guards
- Request/response interceptors
- Custom converters
- File uploads/downloads
- Server-sent events
- HTTP/2 support (via container)
Testing with Mock Framework
@Test
public void testRestEndpoint() throws Exception {
MockRestClient client = MockRestClient.create(MyRestApi.class)
.json()
.build();
// Test GET
Person person = client.get("/person/1")
.run()
.assertStatus().is(200)
.getContent().as(Person.class);
assertEquals("John", person.getName());
// Test POST
Person newPerson = new Person("Jane", 30);
client.post("/person")
.content(newPerson)
.run()
.assertStatus().is(201);
}
Performance Characteristics
- Streaming: Efficient memory usage for large requests/responses
- Thread-Safe: All serializers/parsers are thread-safe
- Caching: Bean metadata is cached for performance
- Minimal Overhead: No reflection during serialization/parsing
Migration from Individual Modules
Before:
<dependency>
<groupId>org.apache.juneau</groupId>
<artifactId>juneau-marshall</artifactId>
<version>${juneau.version}</version>
</dependency>
<dependency>
<groupId>org.apache.juneau</groupId>
<artifactId>juneau-rest-server</artifactId>
<version>${juneau.version}</version>
</dependency>
<dependency>
<groupId>org.apache.juneau</groupId>
<artifactId>juneau-rest-common</artifactId>
<version>${juneau.version}</version>
</dependency>
After:
<dependency>
<groupId>org.apache.juneau</groupId>
<artifactId>juneau-shaded-rest-server</artifactId>
<version>${juneau.version}</version>
</dependency>
Next Steps
- Need Spring Boot? Use juneau-shaded-rest-server-springboot
- Need client functionality too? Use juneau-shaded-all
- Learn about REST server: See REST Server Basics
- Learn about Swagger integration: See Swagger Integration
Share feedback or follow-up questions for this page directly through GitHub.