Page Properties | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Status
| status
| ||||||||||||||||||
colour | Blue | title | Review | Priority | 2 |
Resources & Remarks
Concept article linking to the respecive tutorials
Modification History
|
Table of Contents
Table of Contents | ||||
---|---|---|---|---|
|
...
In the following sections, an arbitrary practical example for each of the three interceptor types is provided for demonstrational purposes. At the end of the article, you will find a link to the Git Repository that houses the complete code project for your inspiration.
Type "getContent"
Imagine the following situation: A large PDF file consisting of several sub-documents is stored in the system. When one specific document is requested, the respective pages should be extracted and returned as a separate PDF file. A good way to achieve this is using an interceptor, i.e., a service that runs in the background listening for its cue. When it occurs, the interceptor is called by the yuuvis® API system and performs its specific task, thereby rerouting the standard flow of the application.
Creating the getContent REST Controller
...
The controller sets the media type of response to PDF and calls the extract
method of the PDFPageSelectorService
.
Modelling a Sub-Document
As a document is identified by its start and end page, the domain object simply represents these two page numbers.
...
Code Block | ||||
---|---|---|---|---|
| ||||
if (range.startsWith("page:")) { ((Map<String, Object>)contentSreamObject.get(0)).remove("range"); String[] bounds = range.substring("page:".length()).split("-"); int startPage = Integer.parseInt(bounds[0]); int endPage = Integer.parseInt(bounds[1]); return new Pages(startPage, endPage); } |
Next, it calls the repository via the REST template and sends a POST request with all object data.
Code Block | ||||
---|---|---|---|---|
| ||||
restTemplate.execute(repositoryUrl + "/" + objectId, HttpMethod.POST, (ClientHttpRequest requestCallback) -> { if (StringUtils.hasLength(authorization)) { // delegate auth header requestCallback.getHeaders().add(HttpHeaders.AUTHORIZATION, authorization); } requestCallback.getHeaders().setAccept(Arrays.asList(MediaType.APPLICATION_PDF)); requestCallback.getHeaders().setContentType(MediaType.APPLICATION_JSON); requestCallback.getBody().write(this.objectMapper.writeValueAsString(requestObjects).getBytes("UTF-8")); }, new StreamResponseExtractor(outputStream, pages.getStartPage(), pages.getEndPage())); |
...
The StreamResponseExtractor
then extracts the pages of the sub-document from the streamed PDF (using PDFBox) and writes them to a new PDF file. The PDFBox functionality is wrapped in the PdfTools
helper class.
Info |
---|
The advantage of streaming is that large files do not need to be copied first but can be handled on the fly. This is not required though: You could just as well get the file from the repository first and store it locally before processing. |
Code Block | ||||
---|---|---|---|---|
| ||||
public static void extractPageFromStream(InputStream inputStream, int startPage, int endPage, OutputStream outputStream) { try { Splitter splitter = new Splitter(); splitter.setStartPage(startPage); splitter.setEndPage(endPage); splitter.setSplitAtPage(endPage - startPage + 1); try (PDDocument document = PDDocument.load(inputStream)) { List<PDDocument> documents = splitter.split(document); if (documents.size() != 1) { throw new IllegalArgumentException("cannot split document, wrong number of split parts"); } try (PDDocument doc = documents.get(0)) { PdfTools.writeDocument(doc, outputStream); } } } catch (Exception e) { LOGGER.info(ExceptionUtils.getMessage(e)); throw new IllegalArgumentException(ExceptionUtils.getMessage(e)); } } private static void writeDocument(PDDocument doc, OutputStream outputStream) throws IOException { try (COSWriter writer = new COSWriter(outputStream)) { writer.write(doc); } } |
...
Create the interceptorConfiguration.json
file, add the following configuration (either JavaScript or SpEL) and save it to the configuration server, either by updating the git repository with the new state, or, in systems running the 'native' profile on the config service, simply changing the configuration file in the file-system of the config service itself.
Note |
---|
Note: You only need one configuration—whether you prefer JavaScript or SpEL is up to you. |
When configuring a getContent interceptor, we can infer the objects' metadata from the predicate.
...
Info | |||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| |||||||||||||||||||||||||||||||||||||||||
Read on
|