Skip to main content

Templated Swaps

The @Swap(template) annotation allows you to associate arbitrary contextual strings with swaps. The primary purpose is for providing template names, such as for Apache FreeMarker, therefore the name 'template'. However, the usage of the string is open-ended.

See the guide: Serialize a type Juneau doesn't know

When to use it​

Use a templated swap when one swap class must produce different output for different POJO classes. The swap implementation receives the template string with each call, so a single FreeMarkerSwap-style class can render many classes, each pointing at its own template file. If one swap serves exactly one class, a plain swap is simpler; see Swaps.

Example​

import org.apache.juneau.marshall.*;
import org.apache.juneau.marshall.json.*;
import org.apache.juneau.marshall.swap.spi.*;

public class TemplatedSwapExample {

// A swap that renders the object using the template named on @Swap.
public static class TemplateSwap extends ObjectSwap<Object,String> {
@Override
public String swap(MarshallingSession session, Object o, String template) throws Exception {
// A real implementation would call FreeMarker or similar with the template name.
return template + ": " + o;
}
}

@Swap(impl=TemplateSwap.class, template="person.txt")
public static class Person {
public String name = "John Smith";

@Override
public String toString() {
return name;
}
}

public static void main(String[] args) throws Exception {
System.out.println(JsonSerializer.DEFAULT.write(new Person()));
}
}

The serializer passes person.txt to swap, so the output is the JSON string "person.txt: John Smith".

Options​

ElementEffect
@Swap(impl)The swap class to apply to the annotated class.
@Swap(template)The template string handed to the swap on every call.
ObjectSwap.forMediaTypes()Restricts the swap to the given media types, for example */html for an HTML-only template.
ObjectSwap.swap(session, object, template)The method to override; template is the annotation value.

The implementation of a FreeMarker swap would look something like this:

// Our templated swap class.
class FreeMarkerSwap extends ObjectSwap {

public MediaType[] forMediaTypes() {
// Make sure this only applies to the HTML serializer.
return MediaType.forStrings("*/html");
}

public Reader swap(MarshallingSession session, Object object, String template) throws Exception {
// Call some method that uses FreeMarker to convert 'o' to raw HTML using
// the 'MyPojo.div.ftl' template.
return getFreeMarkerReader(template, object);
}
}

Pair it with a class by annotating it with @Swap(impl=FreeMarkerSwap.class, template="MyPojo.div.ftl").

See also​