Create xml file using SSJS - xpages

I want to create a xml file using SSJS on server. Is there a way to do so? Can anyone please give a sample code to create a xml file on server.

There are quite some ways. The seemingly easiest one is to create a string that looks like XML.
The next one would be the use of Java DOM classes. There is an article describing it.
Finally you can use SAX with a little helper class
Let us know how it goes.
Update: This would be my version of #Michael's code sample:
<?xml version="1.0" encoding="UTF-8"?>
<!-- XPage which is not rendered but returns data like XML, JSON, etc. -->
<!-- More: http://www.wissel.net/blog/d6plinks/shwl-7mgfbn -->
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" rendered="false">
<xp:this.beforeRenderResponse><![CDATA[#{javascript:try {
var out = facesContext.getOutputStream();
var exCon = facesContext.getExternalContext();
var response = exCon.getResponse(); // get the response context
// set content type, e.g. ...
response.setContentType("text/xml");
// set caching option
response.setHeader("Cache-Control", "no-cache");
// write XML output ...
var result = new biz.taoconsulting.xmltools.SimpleXMLDoc();
result.setOut(out);
result.openTag("result");
result.dateTag("created", new java.util.Date());
result.addSimpleTag("Author",#UserName);
result.openTag("FruitList");
result.addComment("Stephan really likes the fruits example");
var attributes = new java.util.HashMap();
attributes.add("name","Durian");
attributes.add("color","white");
attributes.add("taste","Don't ask");
result.addEmptyTag("fruit",attributes);
result.closeDocument();
// close the output
exCon.responseComplete();
out.close();
} catch (e) {
print(e.toString());
}}]]>
</xp:this.beforeRenderResponse>
</xp:view>
Note the differences here:
I use the beforeRenderResponse event
Access to outputStream instead of writer (stream is not accessible in the afterRenderResponse event)
set the response complete to stop the page from further output, so you can simply type comments on the page what it does
use of the helper class
What seems a little odd when you read the source of the helper class: why not use the output stream in the constructor, so you won't miss it? - I would today add a second constructor with that, but the parameterless constructor allow me to define that class as a managed bean if I fancy that.

to "render" XML in a String as #Stefan suggested I would use the XAgent approach:
<?xml version="1.0" encoding="UTF-8"?>
<!-- XPage which is not rendered but returns data like XML, JSON, etc. -->
<!-- More: http://www.wissel.net/blog/d6plinks/shwl-7mgfbn -->
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" rendered="false">
<xp:this.afterRenderResponse><![CDATA[#{javascript:try {
var writer = facesContext.getResponseWriter(), // get a writer object
response = facesContext.getExternalContext().getResponse(); // get the response context
// set content type, e.g. ...
response.setContentType("text/xml");
// set caching option
response.setHeader("Cache-Control", "no-cache");
// write XML output ...
writer.write(
'<?xml version="1.0"?>\n'
+ '<root>\n'
+ '<entity>Example Content</entity>\n'
+ '</root>\n'
);
// close the stream
writer.endDocument();
} catch (e) {
print(e.toString());
}}]]>
</xp:this.afterRenderResponse>
<xp:this.resources>
<xp:script src="/XBAN.jss" clientSide="false"></xp:script>
</xp:this.resources>
</xp:view>
Simply put his code into a newly created XPage and test it. Modify the lines in writer.write() to fit to your needs.

Related

Jaxb Marshaller.Generate output.xml file containing the same data of the input.xml file with an additional tag indicating the record process result

I'm reading an xml file (Input.xml) using Unmarshall Jaxb using a my Pojo Object.
Reading Input File example with Unmarshaller.
File file = new File(".\\src\\test\\files\\Input.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(MerchantPayments.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
MerchantPayments MpObj = (MerchantPayments) jaxbUnmarshaller.unmarshal(file);
// Process MpObj..
What i need to do now, is to generate an Output.xml file containing the same data of the Input.xml file, but adding a new tag called <result> indicating if the record has been succesfully loaded.
Which is the best way to generate the output.xml file using Jaxb Marshal functionality containing the same data of the input.xml and adding a new tag?
I need to generate a new Pojo of the output.xml file in order to add the new tag or there are others way using Jaxb Marshaller?
Below the Input.xml file and the output.xml file that I need to geneate with the additional tag <result>
Input.xml
<?xml version='1.0' encoding='UTF-8'?>
<payments>
<payment>
<account>123</account>
<order>110000000001</order>
<amount>19.0</amount>
</payment>
<payment>
<account>1234</account>
<order>110000000002</order>
<amount>20.0</amount>
</payment>
</payments>
Output.xml, containing the new tag <result> :
<?xml version='1.0' encoding='UTF-8'?>
<payments>
<payment>
<account>123</account>
<order>110000000001</order>
<amount>19.0</amount>
**<result>Record loaded correctly</result>**
</payment>
<payment>
<account>1234</account>
<order>110000000002</order>
<amount>20.0</amount>
**<result>Record Failed</result>**
</payment>
</payments>
Thanks in advance.
To add new tag in Output.xml, first, you have to add following property corresponding setter/getter method in MerchantPayments class.
#XmlElement(name = "result")
private String result;
After unmarshalling, you'll get MpObj where you have to set "Record Failed" text to result field. Now, you can marshalling MpObj and will get desired output in Output.xml.

xpages FTsearch to excel not working for input fields being blank

My xpage for creating an excel file is:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" rendered="false">
<xp:this.afterRenderResponse><![CDATA[#{javascript:
// some conditions
qstring = tmpArray.join(" AND ").trim();
sessionScope.queryString = qstring;
myView.FTSearch(qstring);
var vec:NotesViewEntryCollection = myView.getAllEntries()
// some code for write
// some code
</xp:view>
what I noticed: for example if I let all the input fields blank, the excel file should contain all the documents saved in my XPiNC application, but it just redirect me to a blank xpage : ( http://domain/XB.nsf/export_hidden.xsp ).
I also use a FTsearch modulo within another button, but the search ( letting all the input fields blank ) is as expected, it works: it displays all the documents via a viewpanel.
I appreciate your time.
If all search fields are empty then you don't need to execute FTSearch(). myView.getAllEntries() will still work and return all documents in view without calling FTSearch().
...
if (cTerms > 0) {
qstring = tmpArray.join(" AND ").trim();
sessionScope.queryString = qstring;
myView.FTSearch(qstring);
}
var vec:NotesViewEntryCollection = myView.getAllEntries();
...

Automatically open the printer dialog after providing PDF download

I am currently opening a pdf file in a new tab in my browser but I need to know how to open a printer dialog to print the pdf jasper report after pressing a commandButton
This is the method that open the pdf in a new tab:
public void printJasper() {
JasperReport compiledTemplate = null;
JRExporter exporter = null;
ByteArrayOutputStream out = null;
ByteArrayInputStream input = null;
BufferedOutputStream output = null;
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
try {
List<String> sampleList = new ArrayList<String>();
sampleList.add("Fist sample string");
sampleList.add("Second sample string");
JRBeanCollectionDataSource beanCollectionDataSource = new JRBeanCollectionDataSource(sampleList);
Map<String, Object> reportValues = new HashMap<String, Object>();
reportValues.put("anyTestValue", "test value");
facesContext = FacesContext.getCurrentInstance();
externalContext = facesContext.getExternalContext();
response = (HttpServletResponse) externalContext.getResponse();
FileInputStream file = new FileInputStream("/any_dir/sample.jasper");
compiledTemplate = (JasperReport) JRLoader.loadObject(file);
out = new ByteArrayOutputStream();
JasperPrint jasperPrint = JasperFillManager.fillReport(compiledTemplate, reportValues, beanCollectionDataSource);
exporter = new JRPdfExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, out);
exporter.exportReport();
input = new ByteArrayInputStream(out.toByteArray());
response.reset();
response.setHeader("Content-Type", "application/pdf");
response.setHeader("Content-Length", String.valueOf(out.toByteArray().length));
response.setHeader("Content-Disposition", "inline; filename=\"fileName.pdf\"");
output = new BufferedOutputStream(response.getOutputStream(), Constants.DEFAULT_BUFFER_SIZE);
byte[] buffer = new byte[Constants.DEFAULT_BUFFER_SIZE];
int length;
while ((length = input.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
output.flush();
} catch (Exception exception) {
/* ... */
} finally {
try {
if (output != null) {
output.close();
}
if (input != null) {
input.close();
}
} catch (Exception exception) {
/* ... */
}
}
facesContext.responseComplete();
}
This is the button that open the pdf file:
<p:commandButton action="#{sampleBB.printJasper}"
ajax="false" onclick="this.form.target='_blank'"
value="#{msg['generate.report']}" />
What I need to do?
With JasperReports
When using JasperReports, simply add this parameter to JasperReports exporter:
exporter.setParameter(JRPdfExporterParameter.PDF_JAVASCRIPT, "this.print();");
This basically instructs Adobe Acrobat to execute the script this.print() when opening the PDF. See also page 79-80 of Adobe Acrobat Scripting Guide. Below is an extract of relevance:
Printing PDF Documents
It is possible to use Acrobat JavaScript to specify whether a PDF document is sent to a
printer or to a PostScript file. In either case, to print a PDF document, invoke the doc
object’s print method. [...]
Without JasperReports
If you don't have control over generation of PDFs and thus can't manipulate it to add the mentioned script, an alternative is to change all the Java/JSF code accordingly so that the PDF file is idempotently available (i.e. the PDF file must be available by just a GET request rather than a POST request). This allows you to embed it in an <iframe> for which it's in turn possible to print its content by JavaScript during onload (keep CORS in mind though).
Simply put, the enduser must be able to download the desired PDF file by just entering its URL in browser's address bar. You can of course make use of GET request query string to specify parameters, allowing a bit more dynamicness. If it's "very large" data, then you can always let JSF put it in the HTTP session or DB and then pass an unique identifier around as request parameter so that the servlet can in turn obtain it from the very same HTTP session or DB.
Whilst possible with some nasty hacks, a JSF backing bean is simply insuitable for the job of idempotently serving a non-JSF response. You'd better use a "plain vanilla" servlet for this. You'll end up with much simpler code. Here's a kickoff example of such a servlet:
#WebServlet("/pdf")
public class PdfServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String foo = request.getParameter("foo");
String bar = request.getParameter("bar");
// ...
// Now just use the same code as in your original bean *without* FacesContext.
// Note that the HttpServletResponse is readily available as method argument!
response.setContentType("application/pdf");
// ...
}
}
With this setup, it's available by http://localhost:8080/context/pdf?foo=abc&bar=xyz.
Once you get that part to work, then you just have to reference it in an <iframe> which uses JavaScript to print its own content window during its load event. You can do this in a JSF page, e.g. /pdf.xhtml:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
>
<h:head>
<style>html, body { height: 100%; margin: 0; overflow: hidden; }</style>
</h:head>
<h:body>
<iframe src="#{request.contextPath}/pdf?#{request.queryString}"
width="100%" height="100%" onload="this.contentWindow.print()" />
</h:body>
</html>
All you need to do in your JSF backing bean is to send a redirect to that page, if necessary with parameters in request query string (which will end up in #{request.queryString} so that the servlet can obtain them via request.getParameter(...)).
Here's a kickoff example:
<h:form target="_blank">
<h:commandButton value="Generate report" action="#{bean.printPdf}" />
</h:form>
public String printPdf() {
// Prepare params here if necessary.
String foo = "abc";
String bar = "xyz";
// ...
return "/pdf?faces-redirect=true"
+ "&foo=" + URLEncoder.encode(foo, "UTF-8")
+ "&bar=" + URLEncoder.encode(bar, "UTF-8");
}
There is a <p:printer> Primefaces's component for that purpose.
Something like this might work, not tested though.
<h:form>
<h:commandButton value="Print" type="button" icon="ui-icon-print">
<p:printer target="pdf" />
</h:commandButton>
<p:media style="display:none;" id="pdf" value="/aPDF.pdf" />
</h:form>
Note :
<p:media> does have a print button to print the displayed pdf.
Edit :
You have to embed the pdf file inside an iframe and use the JavaScript print() function on it, or you can activate the auto-print function in the PDF itself. But it is definitely possible.
See this question on SO : Can a PDF file's print dialog be opened with Javascript?
How to Use JavaScript to Print a PDF
You can't print a URL directly from JavaScript, you can only open the print dialog for the existing page - article and print API.
PDF is generated on the server and sent to the web-browser (as a separate "page") which has to decide how to process it - the user is usually asked if it wants to display or save the PDF.
To "automatically print" (i.e. open a print dialog) an HTML page you would just have something like this:
window.onload = function() {
window.print();
};
But that can't be done for a PDF since it's not an HTML page.
To "automatically print" something other than an HTML page you would need to have a web-browser plug-in to handle PDFs from your server.
Another posibility is to write a GreaseMonkey user-script that would react on *.myserver.com/**.pdf and have it printed. Note: GreaseMonkey is a Mozilla Firefox plug-in.
Heavy weight option
You could accomplish your task by adding print support to your server application. Application requirements:
It would have to be an Intranet application (self-hosted inside the user's network),
Admin user would need to register network printers accessible from the server via a JSP page,
A "print dialog" page where you would select a registered printer and on clicking the "Print" button send a "print" request, for example:
/print?printer=printer1&doc=/reports/report1
I have seen a Java web application that supported this, but as you can see, it's not an easy task.
#Sujan Sivagurunathan
I tried combining the p:printer and p:media by replacing the image on the p:printer demo page with the PDF file from the p:media demo page:
// Replace this line:
<img id="j_idt18:image" src="/showcase/images/nature1.jpg?pfdrid_c=true" alt="">
// With this one:
<object **id="j_idt18:image"** style="display:none;" type="application/pdf" data="/showcase/resources/other/guide.pdf?pfdrid_c=true">Undefined</object>
When you click the Print button you get an empty page. If you omit the style="display:none;" and leave the PDF's height="300px" width="100%" you will get a small rectangle on the page print preview.
Eidt
Thank you, BalusC and Sujan. I agree, there is an option of embedding JavaScript inside the PDF, but that's usually disabled for security reasons.
I suppose the most browser-compatible and user-friendly way is to have a dedicated Print Preview pop-up window with an iframe showing the given PDF via GET request and a Print button to invoke the IFRAME's contentWindow.print().
It is generally a bad idea to just print a document without letting the user select the printer and configure it.

How to get HTML of external website using server-side javascript

I want to get the HTML code / data of any website by using server-side javascript. How can I achieve this?
PS: I need this because from client-side javascript i can't do XMLHttpRequest of external domains due to the same origin policy.
Here is a Quick-n-Dirty solution:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:label id="labelURL">
<xp:this.value>
<![CDATA[#{javascript:
var url:java.net.URL = new java.net.URL("http://google.com");
url.openConnection();
var is:java.io.InputStream = url.openStream();
var c;
var result = "";
while( (c = is.read()) != (-1) ){
result += #Char(c);
}
is.close();
result
}]]>
</xp:this.value>
</xp:label>
</xp:view>
A better solution accessing remote urls is to use http://hc.apache.org/httpclient-3.x/
A little less Q&D way is described here. It uses, as Sven suggested, the Apache HTTP client which provides authentication, automatic redirects etc.

xe:restService not loading data after page is rendered

I have a xPage with following content:
<xe:restService id="restService" preventDojoStore="false">
<xe:this.service>
<xe:viewJsonService viewName="vwChartData"
contentType="text/json">
<xe:this.columns>
<xe:restViewColumn columnName="x" name="valuex"></xe:restViewColumn>
<xe:restViewColumn columnName="y" name="valuey"></xe:restViewColumn>
</xe:this.columns>
</xe:viewJsonService>
</xe:this.service>
</xe:restService>
How to fetch the data after page load? From what I understand it should create a Dojo store, although it never loads the data.
When I add to the page a xe:djxDataGrid, hide it from user, I can easily access the data from created Dojo Store, either by referring directly the restService variable, or through djxDataGrid.
Solution:
<xp:scriptBlock>
<xp:this.value><![CDATA[XSP.addOnLoad( function() {
var ds = eval('restService');
ds.fetch({
onComplete : function(items, request) {
console.log(items);
}
});
});]]></xp:this.value>
</xp:scriptBlock>
When you look at the source code when using a data grid you would see all the source code necessary to link your Dojo store. Watch the XSP.onLoad for trigger code.

Resources