You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2019/12/30 12:40:58 UTC

[isis] 01/03: ISIS-2231: adds in xdocreport service.

This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 4f33f7da8d49e7306296c96496c4c48550cbdd9c
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Mon Dec 30 12:21:21 2019 +0000

    ISIS-2231: adds in xdocreport service.
    
    also the declaration of zip service in parent extensions pom.xml
---
 core/pom.xml                                       |  10 +++
 extensions/lib/xdocreport/impl/pom.xml             |  53 +++++++++++-
 .../extensions/xdocreport/dom/impl/OutputType.java |   6 ++
 .../xdocreport/dom/impl/XDocReportModel.java       |  27 ++++++
 .../xdocreport/dom/impl/XDocReportService.java     |  94 +++++++++++++++++++++
 .../dom/impl/example/Generate0Fields.java          |  34 ++++++++
 .../xdocreport/dom/impl/example/Generate1Docx.java |  61 +++++++++++++
 .../xdocreport/dom/impl/example/Generate2Pdf.java  |  33 ++++++++
 .../dom/impl/example/models/Developer.java         |  12 +++
 .../dom/impl/example/models/Project.java           |  10 +++
 .../example/models/ProjectDevelopersModel.java     |  25 ++++++
 .../impl/example/template/Project-template.docx    | Bin 0 -> 697650 bytes
 .../dom/impl/example/template/project.fields.xml   |  16 ++++
 .../dom/impl/service/XDocReportServiceTest.java    |  58 +++++++++++++
 extensions/lib/zip/impl/pom.xml                    |   8 +-
 extensions/pom.xml                                 |  13 +++
 16 files changed, 455 insertions(+), 5 deletions(-)

diff --git a/core/pom.xml b/core/pom.xml
index 1a5eafe..92de3e7 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -1074,6 +1074,16 @@
 				<artifactId>fr.opensagres.xdocreport.converter.docx.xwpf</artifactId>
 				<version>${xdocreport.version}</version>
 			</dependency>
+			<dependency>
+				<groupId>fr.opensagres.xdocreport</groupId>
+				<artifactId>org.apache.poi.xwpf.converter.pdf</artifactId>
+				<version>${xdocreport.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>fr.opensagres.xdocreport</groupId>
+				<artifactId>org.apache.poi.xwpf.converter.core</artifactId>
+				<version>${xdocreport.version}</version>
+			</dependency>
 
 			<dependency>
 				<groupId>io.swagger</groupId>
diff --git a/extensions/lib/xdocreport/impl/pom.xml b/extensions/lib/xdocreport/impl/pom.xml
index 091772a..b047e7a 100644
--- a/extensions/lib/xdocreport/impl/pom.xml
+++ b/extensions/lib/xdocreport/impl/pom.xml
@@ -18,7 +18,7 @@
 		<groupId>org.apache.isis.extensions</groupId>
 		<artifactId>isis-extensions</artifactId>
 		<version>2.0.0-M3-SNAPSHOT</version>
-		<relativePath>../../pom.xml</relativePath>
+		<relativePath>../../../pom.xml</relativePath>
 	</parent>
 
 	<artifactId>isis-extensions-xdocreport-dom</artifactId>
@@ -32,6 +32,57 @@
 
 	<dependencies>
 
+		<dependency>
+			<groupId>org.apache.isis.core</groupId>
+			<artifactId>isis-applib</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-context</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>fr.opensagres.xdocreport</groupId>
+			<artifactId>fr.opensagres.xdocreport.document.docx</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>fr.opensagres.xdocreport</groupId>
+			<artifactId>fr.opensagres.xdocreport.template.freemarker</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>fr.opensagres.xdocreport</groupId>
+			<artifactId>fr.opensagres.xdocreport.converter.docx.xwpf</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>fr.opensagres.xdocreport</groupId>
+			<artifactId>org.apache.poi.xwpf.converter.pdf</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>fr.opensagres.xdocreport</groupId>
+			<artifactId>org.apache.poi.xwpf.converter.core</artifactId>
+		</dependency>
+
+		<!-- test -->
+		<dependency>
+			<groupId>org.apache.isis.core</groupId>
+			<artifactId>isis-unittestsupport</artifactId>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>com.google.guava</groupId>
+			<artifactId>guava</artifactId>
+			<scope>test</scope>
+		</dependency>
+
+		<!-- provided -->
+		<dependency>
+			<groupId>org.projectlombok</groupId>
+			<artifactId>lombok</artifactId>
+			<scope>provided</scope>
+		</dependency>
+
+
 	</dependencies>
 
 </project>
diff --git a/extensions/lib/xdocreport/impl/src/main/java/org/apache/isis/extensions/xdocreport/dom/impl/OutputType.java b/extensions/lib/xdocreport/impl/src/main/java/org/apache/isis/extensions/xdocreport/dom/impl/OutputType.java
new file mode 100644
index 0000000..276eeaa
--- /dev/null
+++ b/extensions/lib/xdocreport/impl/src/main/java/org/apache/isis/extensions/xdocreport/dom/impl/OutputType.java
@@ -0,0 +1,6 @@
+package org.apache.isis.extensions.xdocreport.dom.impl;
+
+public enum OutputType {
+    DOCX,
+    PDF
+}
diff --git a/extensions/lib/xdocreport/impl/src/main/java/org/apache/isis/extensions/xdocreport/dom/impl/XDocReportModel.java b/extensions/lib/xdocreport/impl/src/main/java/org/apache/isis/extensions/xdocreport/dom/impl/XDocReportModel.java
new file mode 100644
index 0000000..f4253d0
--- /dev/null
+++ b/extensions/lib/xdocreport/impl/src/main/java/org/apache/isis/extensions/xdocreport/dom/impl/XDocReportModel.java
@@ -0,0 +1,27 @@
+package org.apache.isis.extensions.xdocreport.dom.impl;
+
+import java.util.List;
+import java.util.Map;
+
+public interface XDocReportModel {
+
+    @lombok.Data
+    class Data {
+        private final Object obj;
+        private final Class<?> cls;
+        private final boolean list;
+
+        public static <T> Data list(final List<T> objects, final Class<T> cls) {
+            return new Data(objects, cls, true);
+        }
+
+        public static <T> Data object(final T object) {
+            return new Data(object, object.getClass(), false);
+        }
+    }
+    Map<String, Data> getContextData();
+
+}
+
+
+
diff --git a/extensions/lib/xdocreport/impl/src/main/java/org/apache/isis/extensions/xdocreport/dom/impl/XDocReportService.java b/extensions/lib/xdocreport/impl/src/main/java/org/apache/isis/extensions/xdocreport/dom/impl/XDocReportService.java
new file mode 100644
index 0000000..d9ad6ff
--- /dev/null
+++ b/extensions/lib/xdocreport/impl/src/main/java/org/apache/isis/extensions/xdocreport/dom/impl/XDocReportService.java
@@ -0,0 +1,94 @@
+package org.apache.isis.extensions.xdocreport.dom.impl;
+
+import fr.opensagres.xdocreport.core.XDocReportException;
+import fr.opensagres.xdocreport.core.io.internal.ByteArrayOutputStream;
+import fr.opensagres.xdocreport.document.IXDocReport;
+import fr.opensagres.xdocreport.document.registry.XDocReportRegistry;
+import fr.opensagres.xdocreport.template.IContext;
+import fr.opensagres.xdocreport.template.TemplateEngineKind;
+import fr.opensagres.xdocreport.template.formatter.FieldsMetadata;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import javax.annotation.PostConstruct;
+
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.poi.xwpf.converter.core.IXWPFConverter;
+import org.apache.poi.xwpf.converter.pdf.PdfConverter;
+import org.apache.poi.xwpf.converter.pdf.PdfOptions;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+import org.springframework.stereotype.Service;
+
+@Service
+public class XDocReportService {
+
+    PdfOptions pdfOptions;
+
+    @PostConstruct
+    public void init() {
+        pdfOptions = PdfOptions.create();
+    }
+
+    @Programmatic
+    public byte[] render(
+            final byte[] templateBytes,
+            final XDocReportModel dataModel,
+            final OutputType outputType) throws IOException {
+        try {
+            final byte[] docxBytes = toDocx(templateBytes, dataModel);
+
+            switch (outputType) {
+            case PDF:
+                return toPdf(docxBytes);
+            default: // ie DOCX
+                return docxBytes;
+            }
+
+        } catch (XDocReportException e) {
+            throw new IOException(e);
+        }
+    }
+
+    private byte[] toDocx(final byte[] bytes, final XDocReportModel dataModel) throws IOException, XDocReportException {
+        final IXDocReport report = XDocReportRegistry
+                .getRegistry().loadReport(new ByteArrayInputStream(bytes), TemplateEngineKind.Freemarker);
+
+        final IContext context = report.createContext();
+
+        final FieldsMetadata fieldsMetadata = report.createFieldsMetadata();
+
+        final Map<String, XDocReportModel.Data> contextObjects = dataModel.getContextData();
+        for (final Map.Entry<String, XDocReportModel.Data> entry : contextObjects.entrySet()) {
+            final XDocReportModel.Data data = entry.getValue();
+            final String key = entry.getKey();
+            fieldsMetadata.load(key, data.getCls(), data.isList());
+            context.put(key, data.getObj());
+        }
+
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        report.process(context, baos);
+
+        return baos.toByteArray();
+    }
+
+    private byte[] toPdf(final byte[] docxBytes) throws IOException {
+
+        final XWPFDocument document = new XWPFDocument(new ByteArrayInputStream(docxBytes));
+
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        pdfConverter().convert(document, baos, pdfOptions);
+
+        return baos.toByteArray();
+    }
+
+    protected IXWPFConverter<PdfOptions> pdfConverter() {
+        return PdfConverter.getInstance();
+    }
+
+
+}
+
+
+
diff --git a/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/example/Generate0Fields.java b/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/example/Generate0Fields.java
new file mode 100644
index 0000000..e92e073
--- /dev/null
+++ b/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/example/Generate0Fields.java
@@ -0,0 +1,34 @@
+package org.apache.isis.extensions.xdocreport.dom.impl.example;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.isis.extensions.xdocreport.dom.impl.example.models.Developer;
+import org.apache.isis.extensions.xdocreport.dom.impl.example.models.Project;
+
+import fr.opensagres.xdocreport.core.XDocReportException;
+import fr.opensagres.xdocreport.template.TemplateEngineKind;
+import fr.opensagres.xdocreport.template.formatter.FieldsMetadata;
+
+public class Generate0Fields {
+
+    public static void main(String[] args) throws XDocReportException,IOException {
+
+        // 1) Create FieldsMetadata by setting Velocity as template engine
+        FieldsMetadata fieldsMetadata = new FieldsMetadata(TemplateEngineKind.Freemarker.name());
+
+        // 2) Load fields metadata from Java Class
+        fieldsMetadata.load("project", Project.class);
+        // Here load is called with true because model is a list of Developer.
+        fieldsMetadata.load("developers", Developer.class, true);
+
+
+        // 3) Generate XML fields in the file "project.fields.xml".
+        // Extension *.fields.xml is very important to use it with MS Macro XDocReport.dotm
+        // FieldsMetadata#saveXML is called with true to indent the XML.
+        final File xmlFieldsFile = new File("target/project.fields.xml");
+        fieldsMetadata.saveXML(new FileOutputStream(xmlFieldsFile), true);
+    }
+
+}
diff --git a/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/example/Generate1Docx.java b/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/example/Generate1Docx.java
new file mode 100644
index 0000000..a2ac33f
--- /dev/null
+++ b/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/example/Generate1Docx.java
@@ -0,0 +1,61 @@
+package org.apache.isis.extensions.xdocreport.dom.impl.example;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.isis.extensions.xdocreport.dom.impl.example.models.Developer;
+import org.apache.isis.extensions.xdocreport.dom.impl.example.models.Project;
+
+import fr.opensagres.xdocreport.core.XDocReportException;
+import fr.opensagres.xdocreport.document.IXDocReport;
+import fr.opensagres.xdocreport.document.registry.XDocReportRegistry;
+import fr.opensagres.xdocreport.template.IContext;
+import fr.opensagres.xdocreport.template.TemplateEngineKind;
+import fr.opensagres.xdocreport.template.formatter.FieldsMetadata;
+
+public class Generate1Docx {
+
+    public static void main(String[] args) throws IOException,
+            XDocReportException {
+
+        // 1) Load Docx file by filling freemarker template engine and cache
+        // it to the registry
+        InputStream in= new FileInputStream(new File("src/test/java/org/isisaddons/module/xdocreport/dom/example/template/Project-template.docx"));
+        IXDocReport report = XDocReportRegistry.getRegistry().loadReport(in,TemplateEngineKind.Freemarker);
+
+        // 2) Create fields metadata to manage lazy loop (#forech velocity)
+        // for table row.
+        // 1) Create FieldsMetadata by setting freemarker as template engine
+        FieldsMetadata fieldsMetadata = report.createFieldsMetadata();
+
+        // 2) Load fields metadata from Java Class
+        fieldsMetadata.load("project", Project.class);
+        // Here load is called with true because model is a list of Developer.
+        fieldsMetadata.load("developers", Developer.class, true);
+
+        // 3) Create context Java model
+        IContext context = report.createContext();
+
+        Project project = new Project("XDocReport");
+        context.put("project", project);
+
+        List<Developer> developers = new ArrayList<Developer>();
+        developers.add(
+                new Developer("ZERR", "Angelo", "angelo.zerr@gmail.com"));
+        developers.add(
+                new Developer("Leclercq", "Pascal", "pascal.leclercq@gmail.com"));
+        context.put("developers", developers);
+
+        // 4) Generate report by merging Java model with the Docx
+        OutputStream out = new FileOutputStream(new File("target/Project.docx"));
+        report.process(context, out);
+
+    }
+
+}
diff --git a/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/example/Generate2Pdf.java b/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/example/Generate2Pdf.java
new file mode 100644
index 0000000..03e05ea
--- /dev/null
+++ b/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/example/Generate2Pdf.java
@@ -0,0 +1,33 @@
+package org.apache.isis.extensions.xdocreport.dom.impl.example;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.poi.xwpf.converter.pdf.PdfConverter;
+import org.apache.poi.xwpf.converter.pdf.PdfOptions;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+
+import fr.opensagres.xdocreport.core.XDocReportException;
+
+public class Generate2Pdf {
+
+    public static void main(String[] args) throws IOException,
+            XDocReportException {
+
+        // 1) Load DOCX into XWPFDocument
+        InputStream in= new FileInputStream(new File("target/Project.docx"));
+        XWPFDocument document = new XWPFDocument(in);
+
+        // 2) Prepare Pdf options
+        PdfOptions options = PdfOptions.create();
+
+        // 3) Convert XWPFDocument to Pdf
+        OutputStream out = new FileOutputStream(new File("target/Project.pdf"));
+        PdfConverter.getInstance().convert(document, out, options);
+    }
+
+}
diff --git a/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/example/models/Developer.java b/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/example/models/Developer.java
new file mode 100644
index 0000000..1768a4e
--- /dev/null
+++ b/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/example/models/Developer.java
@@ -0,0 +1,12 @@
+package org.apache.isis.extensions.xdocreport.dom.impl.example.models;
+
+import lombok.Data;
+
+@Data
+public class Developer {
+
+    private final String name;
+    private final String lastName;
+    private final String mail;
+
+}
diff --git a/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/example/models/Project.java b/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/example/models/Project.java
new file mode 100644
index 0000000..b2c793a
--- /dev/null
+++ b/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/example/models/Project.java
@@ -0,0 +1,10 @@
+package org.apache.isis.extensions.xdocreport.dom.impl.example.models;
+
+import lombok.Data;
+
+@Data
+public class Project {
+
+    private final String name;
+    
+}
diff --git a/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/example/models/ProjectDevelopersModel.java b/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/example/models/ProjectDevelopersModel.java
new file mode 100644
index 0000000..bbaad82
--- /dev/null
+++ b/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/example/models/ProjectDevelopersModel.java
@@ -0,0 +1,25 @@
+package org.apache.isis.extensions.xdocreport.dom.impl.example.models;
+
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.isis.extensions.xdocreport.dom.impl.XDocReportModel;
+
+import com.google.common.collect.ImmutableMap;
+
+@Data
+public class ProjectDevelopersModel implements XDocReportModel {
+
+    private final Project project;
+    private final List<Developer> developers;
+
+    @Override
+    public Map<String, Data> getContextData() {
+        return ImmutableMap.of(
+                "project", Data.object(project),
+                "developers", Data.list(developers, Developer.class));
+    }
+
+}
diff --git a/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/example/template/Project-template.docx b/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/example/template/Project-template.docx
new file mode 100644
index 0000000..0cc242b
Binary files /dev/null and b/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/example/template/Project-template.docx differ
diff --git a/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/example/template/project.fields.xml b/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/example/template/project.fields.xml
new file mode 100644
index 0000000..004a3ac
--- /dev/null
+++ b/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/example/template/project.fields.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<fields templateEngineKind="Freemarker" >
+	<description><![CDATA[]]></description>
+	<field name="project.name" list="false" imageName="" syntaxKind="">
+		<description><![CDATA[]]></description>
+	</field>
+	<field name="developers.lastName" list="true" imageName="" syntaxKind="">
+		<description><![CDATA[]]></description>
+	</field>
+	<field name="developers.mail" list="true" imageName="" syntaxKind="">
+		<description><![CDATA[]]></description>
+	</field>
+	<field name="developers.name" list="true" imageName="" syntaxKind="">
+		<description><![CDATA[]]></description>
+	</field>
+</fields>
\ No newline at end of file
diff --git a/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/service/XDocReportServiceTest.java b/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/service/XDocReportServiceTest.java
new file mode 100644
index 0000000..38e3431
--- /dev/null
+++ b/extensions/lib/xdocreport/impl/src/test/java/org/apache/isis/extensions/xdocreport/dom/impl/service/XDocReportServiceTest.java
@@ -0,0 +1,58 @@
+package org.apache.isis.extensions.xdocreport.dom.impl.service;
+
+import fr.opensagres.xdocreport.core.io.IOUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.isis.extensions.xdocreport.dom.impl.OutputType;
+import org.apache.isis.extensions.xdocreport.dom.impl.XDocReportService;
+import org.apache.isis.extensions.xdocreport.dom.impl.example.models.Developer;
+import org.apache.isis.extensions.xdocreport.dom.impl.example.models.Project;
+import org.apache.isis.extensions.xdocreport.dom.impl.example.models.ProjectDevelopersModel;
+import org.apache.isis.unittestsupport.jmocking.JUnitRuleMockery2;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class XDocReportServiceTest {
+
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
+
+    @Rule
+    public JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(JUnitRuleMockery2.Mode.INTERFACES_AND_CLASSES);
+
+    XDocReportService service;
+
+    @Before
+    public void setUp() throws Exception {
+        service = new XDocReportService();
+    }
+
+    @Test
+    public void simple() throws Exception {
+
+        // given
+        InputStream in= new FileInputStream(new File("src/test/java/org/isisaddons/module/xdocreport/dom/example/template/Project-template.docx"));
+        final byte[] templateBytes = IOUtils.toByteArray(in);
+
+        Project project = new Project("XDocReport");
+        List<Developer> developers = new ArrayList<>();
+        developers.add(new Developer("ZERR", "Angelo", "angelo.zerr@gmail.com"));
+        developers.add(new Developer("Leclercq", "Pascal", "pascal.leclercq@gmail.com"));
+        final ProjectDevelopersModel dataModel = new ProjectDevelopersModel(project, developers);
+
+        // when
+        final byte[] docxBytes = service.render(templateBytes, dataModel, OutputType.DOCX);
+
+        // then
+        IOUtils.write(docxBytes,new FileOutputStream(new File("target/Project.docx")));
+    }
+
+}
diff --git a/extensions/lib/zip/impl/pom.xml b/extensions/lib/zip/impl/pom.xml
index cb07dec..2bb64d9 100644
--- a/extensions/lib/zip/impl/pom.xml
+++ b/extensions/lib/zip/impl/pom.xml
@@ -41,13 +41,13 @@
 			<artifactId>isis-applib</artifactId>
 		</dependency>
 		<dependency>
-			<groupId>com.google.guava</groupId>
-			<artifactId>guava</artifactId>
-		</dependency>
-		<dependency>
 			<groupId>org.springframework</groupId>
 			<artifactId>spring-context</artifactId>
 		</dependency>
+		<dependency>
+			<groupId>com.google.guava</groupId>
+			<artifactId>guava</artifactId>
+		</dependency>
 
 		<dependency>
 			<groupId>org.projectlombok</groupId>
diff --git a/extensions/pom.xml b/extensions/pom.xml
index d170a9e..9fe4298 100644
--- a/extensions/pom.xml
+++ b/extensions/pom.xml
@@ -196,6 +196,18 @@
 				<version>2.0.0-M3-SNAPSHOT</version>
 			</dependency>
 
+			<dependency>
+				<groupId>org.apache.isis.extensions</groupId>
+				<artifactId>isis-extensions-xdocreport-dom</artifactId>
+				<version>2.0.0-M3-SNAPSHOT</version>
+			</dependency>
+
+			<dependency>
+				<groupId>org.apache.isis.extensions</groupId>
+				<artifactId>isis-extensions-zip-dom</artifactId>
+				<version>2.0.0-M3-SNAPSHOT</version>
+			</dependency>
+
 		</dependencies>
 	</dependencyManagement>
 
@@ -208,6 +220,7 @@
 -->
 		<module>lib/excel/impl</module>
 
+		<module>lib/xdocreport/impl</module>
 		<module>lib/zip/impl</module>
 
 		<module>persistence/h2console/impl</module>