Render Page Components as JSON
CaaS (Content as a Service) is a common need in today’s multi-channel world. Typically CaaS use cases require that the content is devoid of presentation markup so that the consumer can present the content as it desires. Other times comsumers may wish to pull rendered content. This cookbook provides a simple REST example (a single Groovy based rest controller script) that will give you a way to render all of the components associated to a page.
Prerequisites
None
Step 1: Create a REST Controller
- Under Scripts/rest right click and click create controller
Enter get-rendered-components.get as the controller name
Add the following code to the controller.
1import java.io.ByteArrayOutputStream
2import java.io.IOException
3import java.io.PrintWriter
4
5import javax.servlet.Filter
6import javax.servlet.FilterChain
7import javax.servlet.FilterConfig
8import javax.servlet.ServletException
9import javax.servlet.ServletOutputStream
10import javax.servlet.ServletRequest
11import javax.servlet.ServletResponse
12import javax.servlet.http.HttpServletRequest
13import javax.servlet.http.HttpServletResponse
14import javax.servlet.http.HttpServletResponseWrapper
15import javax.servlet.WriteListener
16import groovy.util.XmlSlurper
17
18def result = [:]
19def targetPage = params.pageId
20
21if (targetPage != null) {
22 result.page = targetPage
23
24 def pageItem = siteItemService.getSiteItem(targetPage)
25
26 if (pageItem != null) {
27 def componentPaths = pageItem.queryValues("//include")
28 result.components = []
29
30 if (componentPaths != null) {
31 componentPaths.each { componentPath ->
32 if (componentPath.endsWith(".xml") && !componentPath.startsWith("/site/website") ) {
33 logger.info("Including component ${componentPath} into JSON response")
34
35 def component = [:]
36 component.id = componentPath
37
38 // wrap the response to capture the output
39 def wrappedResponse = new CapturingResponseWrapper(response)
40
41 // "include" the page that does the actual work
42 request.getRequestDispatcher("/crafter-controller/component?path=" + componentPath).include(request, wrappedResponse)
43
44 // get the captured output, parse it and prepare the actual response
45 def capturedOut = wrappedResponse.getCaptureAsString()
46
47 component.markup = capturedOut
48
49 result.components.add(component)
50 }
51 }
52 } else {
53 result.message = "No components found"
54 }
55 } else {
56 result.message = "Page '${targetPage}` not found"
57 }
58} else {
59 result.message = "Parameter pageId is required."
60}
61
62return result
63
64protected class CapturingResponseWrapper extends HttpServletResponseWrapper {
65
66 private final ByteArrayOutputStream capture
67 private ServletOutputStream output
68 private PrintWriter writer
69
70 public CapturingResponseWrapper(HttpServletResponse response) {
71 super(response)
72 capture = new ByteArrayOutputStream(response.getBufferSize())
73 }
74
75 @Override
76 public ServletOutputStream getOutputStream() {
77 if (writer != null) {
78 throw new IllegalStateException("getWriter() has already been called on this response.")
79 }
80
81 if (output == null) {
82 output = new ServletOutputStream() {
83
84 @Override
85 public void write(int b) throws IOException {
86 capture.write(b)
87 }
88
89 @Override
90 public void flush() throws IOException {
91 capture.flush()
92 }
93
94 @Override
95 public void close() throws IOException {
96 capture.close()
97 }
98
99 @Override
100 public void setWriteListener(WriteListener writeListener) {
101 }
102
103 @Override
104 public boolean isReady() {
105 return true
106 }
107 }
108 }
109
110 return output
111 }
112
113 @Override
114 public PrintWriter getWriter() throws IOException {
115 if (output != null) {
116 throw new IllegalStateException("getOutputStream() has already been called on this response.")
117 }
118
119 if (writer == null) {
120 writer = new PrintWriter(new OutputStreamWriter(capture, getCharacterEncoding()))
121 }
122
123 return writer
124 }
125
126 @Override
127 public void flushBuffer() throws IOException {
128 super.flushBuffer()
129
130 if (writer != null) {
131 writer.flush()
132 }
133 else if (output != null) {
134 output.flush()
135 }
136 }
137
138 public byte[] getCaptureAsBytes() throws IOException {
139 if (writer != null) {
140 writer.close()
141 }
142 else if (output != null) {
143 output.close()
144 }
145
146 return capture.toByteArray()
147 }
148
149 public String getCaptureAsString() throws IOException {
150 return new String(getCaptureAsBytes(), getCharacterEncoding())
151 }
152
153}
Step 2: Execute the Service
- Open a browser and hit the following URL: