1. XPages Binary Output
Vi tales ved
The only limitation is your imagination
iZone
John Foldager, izone.dk
DanNotes November 28th 2013
2. About John Foldager
●
●
Born in 1974 and have been working with IT – especially
programming since the age of 7 – at iZone since 1999
Member of Notesnet.dk – association of approx. 25
independent consultants
●
Vice chairman of Eclipse.dk
●
Mentor at Egedal CoderDojo
●
Pro Cross-platform development (IBM i, Linux, Unix, BSD,
Windows, Solaris, AIX, Raspberry Pi, Android, …)
●
Pro Java/OSGi (scalability, deployment, extensibility, …)
●
Pro HTML5/CSS3/JavaScript
●
Follow me on Twitter
@JohnFoldager
iZone
3. Introduction
●
Normal use of XPages uses HTML, Dojo, IBM OneUI etc.
●
Sometimes other formats/content are needed
●
Text output
●
●
Binary output
●
●
●
●
XML (eXtensible Markup Language), JSON (JavaScript Object Notation), CSV
(Comma Separated Values), SVG (Scalable Vector Graphics), …
Media: images (PNG, JPEG, GIF, …), video (MPEG, …), sound (MP3, Ogg, …)
Document formats: PDF (Portable Document Format), OpenXPS (Open XML
Paper Specification), ODF (Open Document Format), OOXML (Office Open
XML), …
Other: SVG (Scalable Vector Graphics), Archives (ZIP, …), …
We will show how to...
●
use XPages, XAgents, NSF servlets and OSGi servlets
●
embed and/or download content
iZone
4. XAgents
●
Who uses XAgents [in the audience]?
●
●
●
First mentioned by Stefan Wissel on http://www.wissel.net/blog/d6plinks/shwl-7mgfbn
XAgents are XPages where property rendered is set to false
and some code is put into beforeRenderResponse (binary)
or afterRenderResponse (text)
Code is SSJS (Server Side JavaScript)
●
●
Evaluated at runtime (lower performance)
●
●
Easy and quick to write because you are on the same 'page'
Harder to debug and unit test
Some examples...
iZone
5. XAgents – XML example
●
Create an XPage where property rendered is set to false
and put the following code in the afterRenderResponse
(SSJS)
●
var external = facesContext.getExternalContext();
var writer = facesContext.getResponseWriter();
var response = external.getResponse();
response.setContentType("text/xml");
response.setHeader("Cache-Control", "no-cache");
writer.write("<?xml version='1.0' encoding='utf-8'?>rn");
writer.write("<say>Hello World!</say>");
writer.endDocument();
facesContext.responseComplete();
iZone
6. XAgents – JSON example
●
Create an XPage where property rendered is set to false
and put the following code in the afterRenderResponse
(SSJS)
●
var external = facesContext.getExternalContext();
var writer = facesContext.getResponseWriter();
var response = external.getResponse();
response.setContentType("application/json");
response.setHeader("Cache-Control", "no-cache");
writer.write("{rn");
writer.write(" 'say':'Hello World!'rn");
writer.write("}rn");
writer.endDocument();
facesContext.responseComplete();
iZone
7. XPages – Other formats
●
Who [in the audience] have tried to deliver non-standard HTML
from an XPage (without using XAgents) and having 100%
control of all content?
●
●
XPages can be set to create non-HTML content very easily
●
●
●
First mentioned by John Foldager on http://xpages.dk/?p=83
NOTE: Several guides on the Internet describes various ways of removing Dojo,
OneUI etc. – but none of them gives you absolutely full control of the entire content.
For the most part you overrule everything for all XPages inside the NSF, even though
you might only want to do so for a single XPage.
Only thing you need to do is set the rendererType to
javax.faces.Text and set createForm to false
Some examples...
iZone
8. XPages – Custom output (1)
●
Create a Hello World XPage
iZone
13. XPages – Custom output (5)
●
Remove form and fields (locally to current XPage)
iZone
14. XPages – Custom output (6)
●
Remove the rest (locally to current XPage)
iZone
15. XPages – Custom output (7)
●
Your own HTML5 content (locally to current XPage)
iZone
16. XPages – HTML5 example
●
Create an XPage with the following source
●
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" createForm="false" rendererType="javax.faces.Text">
<xp:this.afterRenderResponse><![CDATA[#{javascript:
var external = facesContext.getExternalContext();
var response = external.getResponse();
response.setContentType("text/html");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-store");
}]]></xp:this.afterRenderResponse>
<xp:text escape="false" disableTheme="true">
<xp:this.value><![CDATA[#{javascript:'<!DOCTYPE html>n'}]]></xp:this.value>
</xp:text>
<html lang="en">
<head>
<content encoding="utf-8"/>
<title>My HTML5 page</title>
</head>
<body>
<header><h1>My HTML5 page delivered from an XPage</h1></header>
</body>
</xp:view>
iZone
17. XPages – XML example #1
●
Create an XPage with the following source
●
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" createForm="false" rendererType="javax.faces.Text">
<xp:this.afterRenderResponse><![CDATA[#{javascript:
var external = facesContext.getExternalContext();
var response = external.getResponse();
response.setContentType("text/xml");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-store");
}]]></xp:this.afterRenderResponse>
<xp:text escape="false" disableTheme="true">
<xp:this.value><![CDATA[#{javascript:'<?xml version="1.0" encoding="utf-8" ?>n'}]]></xp:this.value>
</xp:text>
<say>Hello World!</say>
</xp:view>
iZone
18. XPages – XML example #2
●
Create an XPage with the following source
●
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" createForm="false" rendererType="javax.faces.Text">
<xp:this.afterRenderResponse><![CDATA[#{javascript:
var external = facesContext.getExternalContext();
var response = external.getResponse();
response.setContentType("text/xml");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-store");
}]]></xp:this.afterRenderResponse>
<xp:text escape="false" disableTheme="true">
<xp:this.value><![CDATA[#{javascript:'<?xml version="1.0" encoding="utf-8" ?>n'}]]></xp:this.value>
</xp:text>
<xp:repeat id="repeat" rows="30" var="dataentry" removeRepeat="true">
<xp:this.facets>
<xp:text disableTheme="true" xp:key="header" escape="false">
<xp:this.value><![CDATA[<customers>]]></xp:this.value>
</xp:text>
<xp:text disableTheme="true" xp:key="footer" escape="false">
<xp:this.value><![CDATA[</customers>]]></xp:this.value>
</xp:text>
</xp:this.facets>
<xp:this.value><![CDATA[#{javascript:[1,2,3,4]}]]></xp:this.value>
<xp:text escape="false" disableTheme="true">
<xp:this.value><![CDATA[#{javascript:"<customer>" + dataentry + "</customer>n"}]]></xp:this.value>
</xp:text>
</xp:repeat>
iZone
</xp:view>
19. What did we learn so far?
●
●
Now we know how to create our own content from an XPage
(disabling all defaults) and from an XAgent (XPage)
So what exactly did we learn?
●
We learned how to overrule whatever XPage engine is normally generating
●
We learned how to use XPages repeat-control and Data Source
●
We learned how to set the Content Type
●
We learned how to set headers (fx. Caching)
●
We basically learned that XPages can be used for sooooooo much more than what we
normally use it for
iZone
20. Download?
●
How can we make the browser download the content?
●
This is actually pretty easy. We just need to add another HTTP Header to the response
●
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" createForm="false" rendererType="javax.faces.Text">
<xp:this.afterRenderResponse><![CDATA[#{javascript:
var external = facesContext.getExternalContext();
var response = external.getResponse();
response.setContentType("text/plain");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-store");
response.setHeader("Content-Disposition", "attachment; filename=MyFilename.txt");
}]]></xp:this.afterRenderResponse>
Hello World!
</xp:view>
iZone
21. Even more control?
●
So can we get even more control?
●
●
●
●
YES!
We can use servlets either from inside the NSF or using an
OSGi bundle, but before we get to that...
We will try to create a Java class that can be called from a
button or link on a normal XPage to download some content
An example...
iZone
22. Download from XPage (1)
●
Steps to follow
Remember Per Henrik Lausten's presentation earlier today?
●
Create a Java Managed Bean class to deliver content
●
Create entry for bean in faces-config.xml
●
Create button or link on XPage to call bean
iZone
23. Download from XPage (2)
●
Steps to follow
●
Create a Java Managed Bean class to deliver content
●
package dk.izone.demos.download;
import
import
import
import
import
import
import
java.io.IOException;
java.io.OutputStream;
java.io.Serializable;
javax.faces.context.ExternalContext;
javax.faces.context.FacesContext;
com.ibm.xsp.webapp.XspHttpServletResponse;
dk.izone.demos.utils.io.FileIO;
public class DownloadBean implements Serializable {
private static final long serialVersionUID = 1L;
public DownloadBean() {}
public void download() {
try {
byte[] file = FileIO.readFile("C:tempMyArchive.zip");
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext external = context.getExternalContext();
XspHttpServletResponse response = (XspHttpServletResponse) external.getResponse();
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=MyArchive.zip");
response.setHeader("Content-Length", String.valueOf(file.length));
OutputStream os = response.getOutputStream();
os.write(file);
os.close();
context.responseComplete();
} catch (IOException e) {
e.printStackTrace();
}
}
}
iZone
24. Download from XPage (3)
●
Steps to follow
●
Create a Java Managed Bean class to deliver content
●
Create entry for bean in faces-config.xml
●
<?xml version="1.0" encoding="UTF-8"?>
<faces-config>
<managed-bean>
<managed-bean-name>MyBean</managed-bean-name>
<managed-bean-class>dk.izone.demos.download.DownloadBean</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
</managed-bean>
</faces-config>
iZone
25. Download from XPage (4)
●
Steps to follow
●
Create a Java Managed Bean class to deliver content
●
Create entry for bean in faces-config.xml
●
Create button or link on XPage to call bean
●
●
<xp:button id="button1" value="Download">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:MyBean.download();}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
<xp:link id="link1" text="Download">
<xp:eventHandler event="onclick" submit="true" refreshMode="complete">
<xp:this.action><![CDATA[#{javascript:MyBean.download();}]]></xp:this.action>
</xp:eventHandler>
</xp:link>
iZone
27. Standard Java? #1
●
Can we get even more control and use standard Java?
●
●
●
YES!
We can use Java Servlets either from inside the NSF or using
an OSGi bundle. We will start by showing the NSF way...
We will show a Java Servlet that
●
will reside inside the NSF so that it can be deployed like we
“use to”
●
●
●
looks “a little bit” like a real standard Java Servlet
core Java developers should be able to work from template
An example...
iZone
28. Standard Java? #1
●
Depend on Extension Library
●
Create Java class that extends DefaultServletFactory
●
●
Create file META-INF/services/
com.ibm.xsp.adapter.servletFactory and put Java
class package and name in
An example...
iZone
29. Standard Java? #2
●
Can we create standard Java Servlets using Eclipse IDE (or
any other IDE based on Eclipse) and deploy to the Domino
server as an OSGi bundle?
●
●
●
YES! We can even do it using an Update Site :-)
We can create servlets to either an Equinox HTTP Service or
Expeditor Web Container (J2EE)
We will show a Java servlet that
●
●
is a real standard Java Servlet
●
●
is an Eclipse OSGi plugin project
core Java developers should be able to work right away
An example...
iZone
31. rd
3 Party Java API Deployment
●
●
There are plenty of Java APIs that can be downloaded on the
Internet and used for various purposes
Examples
●
●
Images
●
Barcodes (Barcode4J, …)
●
Office Files (Apache POI, ODF Toolkit, OOXML, …)
●
PDFs (Apache PDF Box, iText, …)
●
●
Apache Software Foundation (apache.org)
etc.
So lets see how we can deploy these 3rd party Java APIs using
OSGi bundles
iZone
32. Need Help?
●
You are more than welcome to contact “Gang of Four”
●
Jakob Majkilde, majkilde.dk
●
Per Henrik Lausten, phl-consult.dk
●
John Dalsgaard, dalsgaard-data.dk
●
John Foldager, izone.dk
iZone
33. Links
●
Here are some links that refer to related information
●
DOCTYPE – http://www.dominoguru.com/pages/change_xpage_doctype.html
●
Domino OSGi development – http://www.slideshare.net/fiorep/domino-osgi-development
iZone
34. Questions? Contact!
●
You are more than welcome to contact me directly
●
Website: http://izone.dk
●
Phone: +45 20 22 22 11
●
Email: john.foldager@izone.dk
●
LinkedIn: http://dk.linkedin.com/in/foldager
●
Twitter: @JohnFoldager
●
Google+: +JohnFoldager
●
http://john.foldager.tel
iZone