Session Options via HTTP
Juneau REST supports overriding serializer and parser session properties on a per-request basis via HTTP headers or query parameters. This allows clients to control aspects of marshalling (such as whitespace formatting, bean type annotations, etc.) without server-side code changes.
Overview
The feature works at two levels:
- Server-side: Configure which properties clients are allowed to override using
@Restor@RestOpannotations. - Client-side: Send the allowed properties via HTTP headers or query parameters.
Server Configuration
@Rest Level (applies to all operations in the class)
@Rest(
serializers=JsonSerializer.class,
parsers=JsonParser.class,
allowedSerializerOptions={"useWhitespace", "addBeanTypes", "sortCollections"},
allowedParserOptions={"trimStrings", "validateEnd"}
)
public class MyResource extends BasicRestServlet {
@RestGet
public MyBean get() { ... }
}
@RestOp Level (applies to a specific operation)
@RestGet(
allowedSerializerOptions={"useWhitespace"},
allowedParserOptions={"trimStrings"}
)
public MyBean get() { ... }
Overriding Inheritance with noInherit
By default, operation-level allowedSerializerOptions and allowedParserOptions are merged with class-level values. Use noInherit to override and replace the parent values:
@Rest(allowedSerializerOptions={"useWhitespace", "addBeanTypes"})
public class MyResource extends BasicRestServlet {
// Only allows "sortCollections" - ignores parent "useWhitespace" and "addBeanTypes"
@RestGet(
allowedSerializerOptions={"sortCollections"},
noInherit={"allowedSerializerOptions"}
)
public MyBean get() { ... }
}
BasicUniversalConfig
Resources using BasicUniversalConfig have a comprehensive default allowlist that covers the most common and safe session properties for all supported serializers and parsers.
Client Usage
Juneau REST Client (classic)
The RestClient (classic) and RestRequest (classic) APIs provide dedicated methods for setting session options. These convenience methods live on the classic REST client stack (org.apache.juneau.rest.client.classic) only — the default next-generation RestClient does not have them.
RestClient client = RestClient.create()
.rootUrl("http://localhost:8080/myresource")
.build();
Via HTTP Headers (JSON5 format)
// Builder-level (applies to all requests)
RestClient client = RestClient.create()
.rootUrl("http://localhost:8080/myresource")
.serializerSessionOptionsHeader("{useWhitespace:true,addBeanTypes:false}")
.build();
// Request-level
client.get("/mybean")
.serializerSessionOptionsHeader("{useWhitespace:true}")
.run()
.getContent().as(MyBean.class);
// Map form (serialized as JSON5)
client.get("/mybean")
.serializerSessionOptionsHeader(Map.of("useWhitespace", true))
.run()
.getContent().as(MyBean.class);
Via Query Parameters (UON format)
// Builder-level (applies to all requests via default query params)
RestClient client = RestClient.create()
.rootUrl("http://localhost:8080/myresource")
.serializerSessionOptionsQueryDefault("(useWhitespace=true)")
.build();
// Request-level
client.get("/mybean")
.serializerSessionOptionsQuery("(useWhitespace=true)")
.run()
.getContent().as(MyBean.class);
Parser Options
// Parser options work the same way
client.post("/mybean", body)
.parserSessionOptionsHeader("{trimStrings:true}")
.run();
Raw HTTP
Without the Juneau client, you can send options via raw HTTP:
Header format (JSON5/JSON map):
X-Juneau-Serializer-Options: {useWhitespace:true,addBeanTypes:false}
X-Juneau-Parser-Options: {trimStrings:true}
Query parameter format (UON map):
GET /myresource/mybean?juneauSerializerOptions=(useWhitespace=true)
Programmatic Override
Server-side code can also set session properties programmatically via RestRequest:
@RestGet
public MyBean get(RestRequest req) {
// These are applied regardless of allowedSerializerOptions
req.setSerializerSessionProperty("addBeanTypes", true);
req.setSerializerSessionProperty("maxIndent", 2);
return myBean;
}
Programmatic values and HTTP-provided values are merged, with programmatic values taking precedence.
Safe Properties
Not all session properties are safe to expose via HTTP. Properties that control internal server behavior (like javaMethod, resolver, schema, outer) should never be in the allowlist.
Safe properties to expose include formatting and output control properties:
| Property | Applies To | Description |
|---|---|---|
useWhitespace | Writers | Enable whitespace in output |
maxIndent | Writers | Maximum indentation level |
quoteChar | Writers | Quote character for strings |
keepNullProperties | Serializers | Include null-valued properties |
trimStrings | Serializers/Parsers | Trim string values |
addBeanTypes | Serializers | Add _type annotations |
addRootType | Serializers | Add root type annotation |
sortCollections | Serializers | Sort collections before serializing |
sortMaps | Serializers | Sort maps before serializing |
trimEmptyCollections | Serializers | Remove empty collections |
trimEmptyMaps | Serializers | Remove empty maps |
binaryFormat | Binary serializers | Binary encoding format (BASE64, HEX, etc.) |
escapeSolidus | JSON | Escape forward slashes (/) |
encoding | UON | URL-encode special characters |
validateEnd | JSON/UON parsers | Validate end of input |
expandedParams | URL-encoding parser | Use expanded parameter format |
preserveRootElement | XML parser | Preserve root XML element |
Security Considerations
- Only add properties to the allowlist that clients should be permitted to change.
- Properties controlling server internals (e.g.,
javaMethod,schema) must never be exposed. - The allowlist is enforced on the server; clients cannot override the enforcement.
- If a client sends a disallowed property, the server returns a
400 Bad Request.