I am trying to integrate my Pentaho generated reports with a Java application. My reports are based on OLAP data and written using MDX queries. I found an example on one of the blogs and used it as foundation. My code is:
package org.pentaho.reporting.engine.classic.samples;
import in.nic.spaconsole.ServletContextProvider;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Map;
import java.util.HashMap;
import org.pentaho.reporting.engine.classic.core.DataFactory;
import org.pentaho.reporting.engine.classic.core.MasterReport;
import org.pentaho.reporting.engine.classic.core.ReportProcessingException;
import org.pentaho.reporting.libraries.resourceloader.Resource;
import org.pentaho.reporting.libraries.resourceloader.ResourceException;
import org.pentaho.reporting.libraries.resourceloader.ResourceManager;
/**
* Generates a report in the following scenario:
* <ol>
* <li>The report definition file is a .prpt file which will be loaded and parsed
* <li>The data factory is a simple JDBC data factory using HSQLDB
* <li>There are no runtime report parameters used
* </ol>
*/
public class Sample1 extends AbstractReportGenerator
{
/**
* Default constructor for this sample report generator
*/
public Sample1()
{
}
/**
* Returns the report definition which will be used to generate the report. In this case, the report will be
* loaded and parsed from a file contained in this package.
*
* #return the loaded and parsed report definition to be used in report generation.
*/
public MasterReport getReportDefinition(String reportPath)
{
ResourceManager manager = new ResourceManager();
manager.registerDefaults();
try {
Resource res = manager.createDirectly(new URL(reportPath),
MasterReport.class);
MasterReport report = (MasterReport) res.getResource();
return report;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Returns the data factory which will be used to generate the data used during report generation. In this example,
* we will return null since the data factory has been defined in the report definition.
*
* #return the data factory used with the report generator
*/
public DataFactory getDataFactory()
{
return null;
}
/**
* Returns the set of runtime report parameters. This sample report uses the following three parameters:
* <ul>
* <li><b>Report Title</b> - The title text on the top of the report</li>
* <li><b>Customer Names</b> - an array of customer names to show in the report</li>
* <li><b>Col Headers BG Color</b> - the background color for the column headers</li>
* </ul>
*
* #return <code>null</code> indicating the report generator does not use any report parameters
*/
public Map<String, Object> getReportParameters()
{
final Map parameters = new HashMap<String, Object>();
parameters.put("stday", 28);
parameters.put("styear", 2012);
parameters.put("stmonth", 10);
parameters.put("eday", 28);
parameters.put("eyear", 2012);
parameters.put("emonth", 10);
parameters.put("Sitesearch","india.gov.in");
parameters.put("firstResult",1);
parameters.put("lastResult", 100);
parameters.put("Pagenumber",1);
return parameters;
}
/**
* Simple command line application that will generate a PDF version of the report. In this report,
* the report definition has already been created with the Pentaho Report Designer application and
* it located in the same package as this class. The data query is located in that report definition
* as well, and there are a few report-modifying parameters that will be passed to the engine at runtime.
* <p/>
* The output of this report will be a PDF file located in the current directory and will be named
* <code>SimpleReportGeneratorExample.pdf</code>.
*
* #param args none
* #throws IOException indicates an error writing to the filesystem
* #throws ReportProcessingException indicates an error generating the report
*/
public static void main(String[] args) throws IOException, ReportProcessingException
{
final File outputFilenamehtml = new File(Sample1.class.getSimpleName() + ".html");
final File outputFilenamepdf = new File(Sample1.class.getSimpleName() + ".pdf");
// Generate the report
// new Sample1().generateReport(AbstractReportGenerator.OutputType.PDF, outputFilenamepdf);
// System.err.println("Generated the report [" + outputFilenamepdf.getAbsolutePath() + "]");
// new Sample1().generateReport(AbstractReportGenerator.OutputType.HTML, outputFilenamehtml);
// Output the location of the file
//System.err.println("Generated the report111 [" + outputFilenamehtml.getAbsolutePath() + "]");
}
public void report(String Path) throws IllegalArgumentException, ReportProcessingException, IOException {
// TODO Auto-generated method stub
// final File outputFilenamehtml = new File(Sample1.class.getSimpleName() + ".html");
final File outputFilenamepdf = new File(Sample1.class.getSimpleName() + ".pdf");
// Generate the report
new Sample1().generateReport(AbstractReportGenerator.OutputType.PDF, outputFilenamepdf,Path);
System.err.println("Generated the report [" + outputFilenamepdf.getAbsolutePath() + "]");
// new Sample1().generateReport(AbstractReportGenerator.OutputType.HTML, outputFilenamehtml,Path);
// Output the location of the file
// System.err.println("Generated the report111 [" + outputFilenamehtml.getAbsolutePath() + "]");
}
}
Abstractreportgenerator.java
/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* Copyright (c) 2009 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.reporting.engine.classic.samples;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;
import org.pentaho.reporting.engine.classic.core.ClassicEngineBoot;
import org.pentaho.reporting.engine.classic.core.DataFactory;
import org.pentaho.reporting.engine.classic.core.MasterReport;
import org.pentaho.reporting.engine.classic.core.ReportProcessingException;
import org.pentaho.reporting.engine.classic.core.layout.output.AbstractReportProcessor;
import org.pentaho.reporting.engine.classic.core.modules.output.pageable.base.PageableReportProcessor;
import org.pentaho.reporting.engine.classic.core.modules.output.pageable.pdf.PdfOutputProcessor;
import org.pentaho.reporting.engine.classic.core.modules.output.table.base.FlowReportProcessor;
import org.pentaho.reporting.engine.classic.core.modules.output.table.base.StreamReportProcessor;
import org.pentaho.reporting.engine.classic.core.modules.output.table.html.AllItemsHtmlPrinter;
import org.pentaho.reporting.engine.classic.core.modules.output.table.html.FileSystemURLRewriter;
import org.pentaho.reporting.engine.classic.core.modules.output.table.html.HtmlOutputProcessor;
import org.pentaho.reporting.engine.classic.core.modules.output.table.html.HtmlPrinter;
import org.pentaho.reporting.engine.classic.core.modules.output.table.html.StreamHtmlOutputProcessor;
import org.pentaho.reporting.engine.classic.core.modules.output.table.xls.FlowExcelOutputProcessor;
import org.pentaho.reporting.libraries.repository.ContentLocation;
import org.pentaho.reporting.libraries.repository.DefaultNameGenerator;
import org.pentaho.reporting.libraries.repository.stream.StreamRepository;
/**
* This is the base class used with the report generation examples. It contains the actual <code>embedding</code>
* of the reporting engine and report generation. All example embedded implementations will need to extend this class
* and perform the following:
* <ol>
* <li>Implement the <code>getReportDefinition()</code> method and return the report definition (how the report
* definition is generated is up to the implementing class).
* <li>Implement the <code>getTableDataFactory()</code> method and return the data factory to be used (how
* this is created is up to the implementing class).
* <li>Implement the <code>getReportParameters()</code> method and return the set of report parameters to be used.
* If no report parameters are required, then this method can simply return <code>null</code>
* </ol>
*/
public abstract class AbstractReportGenerator
{
/**
* The supported output types for this sample
*/
public static enum OutputType
{
PDF, EXCEL, HTML
}
/**
* Performs the basic initialization required to generate a report
*/
public AbstractReportGenerator()
{
// Initialize the reporting engine
ClassicEngineBoot.getInstance().start();
}
/**
* Returns the report definition used by this report generator. If this method returns <code>null</code>,
* the report generation process will throw a <code>NullPointerException</code>.
*
* #return the report definition used by thus report generator
*/
public abstract MasterReport getReportDefinition(String Path);
/**
* Returns the data factory used by this report generator. If this method returns <code>null</code>,
* the report generation process will use the data factory used in the report definition.
*
* #return the data factory used by this report generator
*/
public abstract DataFactory getDataFactory();
/**
* Returns the set of parameters that will be passed to the report generation process. If there are no parameters
* required for report generation, this method may return either an empty or a <code>null</code> <code>Map</code>
*
* #return the set of report parameters to be used by the report generation process, or <code>null</code> if no
* parameters are required.
*/
public abstract Map<String, Object> getReportParameters();
/**
* Generates the report in the specified <code>outputType</code> and writes it into the specified
* <code>outputFile</code>.
*
* #param outputType the output type of the report (HTML, PDF, HTML)
* #param outputStream2 the file into which the report will be written
* #throws IllegalArgumentException indicates the required parameters were not provided
* #throws IOException indicates an error opening the file for writing
* #throws ReportProcessingException indicates an error generating the report
*/
public void generateReport(final OutputType outputType,File outputFile,String Path)
throws IllegalArgumentException, IOException, ReportProcessingException
{
if (outputFile == null)
{
throw new IllegalArgumentException("The output file was not specified");
}
OutputStream outputStream = null;
try
{
// Open the output stream
outputStream = new BufferedOutputStream(new FileOutputStream(outputFile));
// Generate the report to this output stream
generateReport(outputType, outputStream,Path);
}
finally
{
if (outputStream != null)
{
outputStream.close();
}
}
}
/**
* Generates the report in the specified <code>outputType</code> and writes it into the specified
* <code>outputStream</code>.
* <p/>
* It is the responsibility of the caller to close the <code>outputStream</code>
* after this method is executed.
*
* #param outputType the output type of the report (HTML, PDF, HTML)
* #param outputStream the stream into which the report will be written
* #throws IllegalArgumentException indicates the required parameters were not provided
* #throws ReportProcessingException indicates an error generating the report
*/
public void generateReport(final OutputType outputType, OutputStream outputStream,String Path)
throws IllegalArgumentException, ReportProcessingException
{
if (outputStream == null)
{
throw new IllegalArgumentException("The output stream was not specified");
}
// Get the report and data factory
final MasterReport report = getReportDefinition(Path);
final DataFactory dataFactory = getDataFactory();
// Set the data factory for the report
if (dataFactory != null)
{
report.setDataFactory(dataFactory);
}
// Add any parameters to the report
final Map<String, Object> reportParameters = getReportParameters();
if (null != reportParameters)
{
for (String key : reportParameters.keySet())
{
report.getParameterValues().put(key, reportParameters.get(key));
}
}
// Prepare to generate the report
AbstractReportProcessor reportProcessor = null;
try
{
// Greate the report processor for the specified output type
switch (outputType)
{
case PDF:
{
final PdfOutputProcessor outputProcessor =
new PdfOutputProcessor(report.getConfiguration(), outputStream, report.getResourceManager());
reportProcessor = new PageableReportProcessor(report, outputProcessor);
break;
}
case EXCEL:
{
final FlowExcelOutputProcessor target =
new FlowExcelOutputProcessor(report.getConfiguration(), outputStream, report.getResourceManager());
reportProcessor = new FlowReportProcessor(report, target);
break;
}
case HTML:
{
final StreamRepository targetRepository = new StreamRepository(outputStream);
final ContentLocation targetRoot = targetRepository.getRoot();
final HtmlOutputProcessor outputProcessor = new StreamHtmlOutputProcessor(report.getConfiguration());
final HtmlPrinter printer = new AllItemsHtmlPrinter(report.getResourceManager());
printer.setContentWriter(targetRoot, new DefaultNameGenerator(targetRoot, "index", "html"));
printer.setDataWriter(null, null);
printer.setUrlRewriter(new FileSystemURLRewriter());
outputProcessor.setPrinter(printer);
reportProcessor = new StreamReportProcessor(report, outputProcessor);
break;
}
}
// Generate the report
reportProcessor.processReport();
}
finally
{
if (reportProcessor != null)
{
reportProcessor.close();
}
}
}
}
and I have a controller that ivokes this sample1.java
#POST
#Path("/get/reportDisplay")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.TEXT_HTML)
public Response exportReport(final ReportBean reportBean,
#Context final HttpServletRequest request,
#Context final HttpServletResponse response,
#Context final ServletContext context) throws IOException,
ParseException, InstantiationException, IllegalAccessException,
ClassNotFoundException, SQLException, JRException, IllegalArgumentException,ReportProcessingException {
String reportPath ="file://" +context.getRealPath("anor_admin.prpt");
Sample1 sample=new Sample1();
sample.report(reportPath);
return Response.status(200).build();
}
//End of Methods
} //End of class
But I am getting errors and not able to preview my reports. Please help me with this.
I've successfully embedded Report Engine in a web application but I had to fix some classpath errors in order to get it work.
Be sure your war includes report-engine-classic.core.jar and lib*.jar from pentaho-library.
You'll need extra dependencies if you use charts.
What kind of errors are you getting?
Related
I have to generate pdf of HTML page. I have written a method for this but it generates an error. Please guide me where I'm wrong. Thank You!
public void htmlToPdf(
String htmlPath,
File pdfFile
) throws IOException, DocumentException {
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(
document,
new FileOutputStream(pdfFile)
);
document.open();
XMLWorkerHelper.getInstance().parseXHtml(
writer,
document,
new FileInputStream(htmlPath),
Charset.forName("UTF-8")
);
document.close();
}
Error :
Cannot resolve method 'parseXHtml(com.lowagie.text.pdf.PdfWriter, com.lowagie.text.Document, java.io.FileInputStream, java.nio.charset.Charset)'
So you want to generate PDFs from HTML with Java? (check EDIT 2020 at the bottom)
Here is the procedure I am using with flying-saucer.
Format your HTML with CSS 2.1
Write the process to generate a PDF
Create the PDF generator interface
Use a custom object to wrap images with attributes for further formatting
Implements your interface with your PDF parameters and images
1. Format your HTML with CSS 2.1
Example can be a JSP with ELs, any other template (you will be able to get the
generated HTML with parameters with an internal POST request), or just static
HTML.
You cannot use proportionnal values like em, rem, vh, vw or complex
CSS like animations.
You can use <style> </style> tag or inline style= attribute
Here is an example of a JSP in my webapp.
<!DOCTYPE html>
<%# page session="false"
language="java"
contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"
isELIgnored="false" %>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<META CHARSET="UTF-8" />
<title>My PDF</title>
<style>
/* you can add reset css too */
/* stylesheet */
body { font-family: sans-serif; }
.someCSSClass {}
.anotherCSSClass {}
</style>
</head>
<body>
<div class="someCSSClass">
<p class="anotherCSSClass" style="line-height:16px;">
${ param.aParameter }
</p>
2. Write the process to generate a PDF with an interface
Why using an interface? Because in the case you need to generate additional
PDFs from different models you will not have to write the same logic to
generate each PDFs.
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.xhtmlrenderer.pdf.ITextRenderer;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfImage;
import com.itextpdf.text.pdf.PdfIndirectObject;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import main.java.bean.ImagePDF;
import main.java.interface.PDFInterface;
import main.java.bean.Constants;
/**
* PDFGenerator
* Class to generate PDF (can implement Servlet).
*/
public class PDFGenerator {
private static final String TMP_DIR = System.getProperty("java.io.tmpdir");
/*
* May not be a GET, can be simple method call for local application or
* whatever you need
*/
#Override
protected void goGet(
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
PDFInterface pdfImplementation = null;
/*
* instance your PDF Model implementation according to this
* parameter (for example)
*/
int pdfModel = Integer.parseInt(
request.getParameter("requestedPDFModel")
);
switch (pdfModel) {
case Constants.PDF_MODEL_1:
pdfImplementation = new PDFImplementationOne();
/*
* You could get the image reference from GET request too,
* or from database or from constants
*/
pdfImplementation.addImage(
"image1.png",
120,
50,
"image_name1",
request
);
break;
case Constants.PDF_MODEL_2:
pdfImplementation = new PDFImplementationTwo();
pdfImplementation.addImage(
"image2.png",
350,
70,
"image_name2",
request
);
break;
default :
System.out.println("Cannot find an implementation for the requested PDF.");
return null;
}
String html = null;
/*
Get the HTML from an URL : if your implementation returns null
then you can for example decide to get the HTML from a file in your implementation
*/
if (pdfImplementation.getUrl(request) != null) {
// Send POST request to generate the HTML from a template (JSP, JSF, Thymeleaf, ...)
URLConnection connection = new URL(
pdfImplementation.getUrl(request)
+pdfImplementation.getEncodedQueryString()
).openConnection();
connection.setDoOutput(true); // POST : remove this to do a GET
connection.setRequestProperty("Accept-Charset", "UTF-8");
connection.setRequestProperty(
"Content-Type",
"application/x-www-form-urlencoded;charset=UTF-8"
);
try (OutputStream output = connection.getOutputStream()) {
output.write(
pdfImplementation
.getEncodedQueryString()
.getBytes(StandardCharsets.UTF_8)
);
}
// Open an input stream on the response
BufferedReader in = new BufferedReader(
new InputStreamReader(connection.getInputStream())
);
StringBuilder sb = new StringBuilder();
// A line in our generated HTML
String inputLine;
// Read all HTML lines and concatenate
while ((inputLine = in.readLine()) != null) {
sb.append(inputLine);
}
html = sb.toString();
in.close();
}
// Get the HTML from a File
else {
html = String.join(
"",
Files.readAllLines(pdfImplementation.getHTMLFile().toPath())
);
}
// Create a temp file to make the PDF
File tempPDFFile = new File(
TMP_DIR + pdfImplementation.getGeneratedPDFFileName()
);
if (!tempPDFFile.exists()) { tempPDFFile.createNewFile(); }
FileOutputStream fos = new FileOutputStream(tempPDFFile);
// Output the HTML to the temp PDF file
new ITextRenderer() {{
setDocumentFromString(html);
layout();
createPDF(fos);
}};
fos.close();
// Create your final PDF file
File pdf = new File(pdfImplementation.getPDFFilename());
// Add images if needed
addImageToPDF(pdfImplementation, tempPDFFile, pdf);
// Write in response if you need servlet implementation
writePDFContentToResponse(pdf, response);
}
/**
* writePDFContentToResponse
* #param pdf : the final PDF file
* #param response : a HTTPServletResponse to write PDF file bytes
* #throws IOException
*/
void writePDFContentToResponse(
File pdf,
HttpServletResponse response
) throws IOException {
InputStream fis = new FileInputStream(pdf);
String mimeType = getServlet().getServletContext()
.getMimeType(pdf.getAbsolutePath());
response.setContentType(
mimeType != null ? mimeType : "application/octet-stream"
);
response.setContentLength((int) pdf.length());
response.setHeader(
"Content-Disposition",
"attachment; filename="+pdf.getName()+".pdf"
);
ServletOutputStream os = response.getOutputStream();
byte[] bufferData = new byte[1024];
int read = 0;
while((read = fis.read(bufferData)) != -1) {
os.write(bufferData, 0, read);
}
os.flush();
os.close();
fis.close();
response.flushBuffer();
Files.delete(pdf.toPath());
}
/**
* addImageToPDF
*
* #param pdfImplementation : the pdfImplementation to get the array of
* custom image objects ImagePDF.
* #param tempPDFFile : the temp PDF file with already HTML content
* converted.
* #param pdf : the final PDF file which will have images stamped.
* #throws DocumentException
* #throws IOException
*/
void addImageToPDF(
PDFInterface pdfImplementation,
File tempPDFFile,
File pdf
) throws DocumentException, IOException {
PdfReader reader = new PdfReader(new FileInputStream(tempPDFFile));
PdfStamper stamper = new PdfStamper(
reader,
new FileOutputStream(pdf)
);
for (ImagePDF img: pdfImplementation.getImages()) {
Image image = img.getImage();
image.scalePercent(img.getScale());
PdfImage stream = new PdfImage(image, "", null);
stream.put(
new PdfName("ITXT_SpecialId"),
new PdfName("123456789")
);
PdfIndirectObject ref = stamper.getWriter().addToBody(stream);
image.setDirectReference(ref.getIndirectReference());
image.setAbsolutePosition(
img.getWidthPosition(),
img.getHeightPosition()
);
PdfContentByte over = stamper.getOverContent(1);
over.addImage(image);
}
stamper.close();
reader.close();
}
}
3. Create the PDF generator interface
import java.io.File;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import com.itextpdf.text.BadElementException;
/**
* PDFInterface
* Interface to define the behavior a PDF model has to implement.
*/
public interface PDFInterface {
/**
* getUrl
* #param request the HTTPServletRequest to fetch parameters for the PDF
* #return the URL target to make a HTTP POST request to get the generated
* HTML (for example if you are making a HTTP POST on a JSP to generate
* HTML dynamically.
*/
String getUrl(HttpServletRequest request);
/**
* getHTMLFile
* #return return the HTML file from the local storage to be read to get
* the HTML.
*/
File getHTMLFile();
/**
* setParametres
* #param object : an object or a list of objects to be encoded to the
* query String to generate the PDF.
*/
void setParametres(Candidat candidat);
String getEncodedQueryString();
/**
* getImages
* #return a custom ImagePDF object with needed attributes to add an image
* after the PDF has been generated has the HTML cannot be read to get
* image during the generation of the PDF.
*/
List<ImagePDF> getImages();
/**
* addImage
* #param url : the URL to get the image
* #param x : the X position
* #param y : the Y position
* #param name : the name of the image
* #param request : the HTTPServletRequest to generate the relative link
* to fetch the image.
* #param scale : the scale of the image
* #throws BadElementException
* #throws IOException
*/
void addImage(
String url,
float x,
float y,
String name,
HttpServletRequest request,
float scale
) throws BadElementException, IOException;
/**
* getPDFFilename
* #return : the name of the PDF file to be generated
*/
String getPDFFilename();
}
4. The ImagePDF object (in case you need to add image to your PDF)
import java.io.IOException;
import com.itextpdf.text.BadElementException;
import com.itextpdf.text.Image;
/**
* ImagePDF
* Class for a custom ImagePDF object to fit needs to stamp an image on a
* generated PDF (URI to get the image, scale, positions x y ...).
*/
public class ImagePDF implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private Image image;
private float widthPosition;
private float heightPosition;
private String name;
private Float scale;
/**
* ImagePDF
* #param urlImage : the URL to fetch the image
* #param heightPosition : the y position on the PDF canvas
* #param widthPosition : the x position on the PDF canvas
* #param name : the name of the image
* #param scale : the scale of the image on the PDF canvas
* #throws BadElementException
* #throws IOException
*/
public ImagePDF(
String urlImage,
float widthPosition,
float heightPosition,
String name,
Float scale
) throws BadElementException, IOException {
this.image = Image.getInstance(urlImage);
this.heightPosition = heightPosition;
this.widthPosition = widthPosition;
this.name = name;
this.scale = scale;
}
// Getters and setters ...
5. Implements your interface for your PDF parameters
(used in example above)
/**
* PDFImplementationOne
* The PDFImplementation to generate a specific PDF.
*/
public class PDFImplementationOne implements PDFInterface {
private static final String PARAM_1 = "param1";
private static final String PARAM_2 = "param2";
private Map<String, String> parameters;
private List<ImagePDF> images;
/**
* PDFImplementationOne
* You can pass service to add information retreival from DB or objects to
* pass to parameters in the constructor if needed.
*/
public PDFImplementationOne (CustomObject aParameter) {
this.parameters = new HashMap<>();
this.images = new ArrayList<>();
// in case you need parameters, passed in constructor
setParametres(aParameter);
}
/* (non-Javadoc)
* #see main.java.interface.PDFInterface#getUrl()
*/
#Override
public String getUrl(HttpServletRequest request) {
/*
* This is an example in case your generate your HTML from JSP with
* parameters, if it is from static file then return null
*/
StringBuilder sb = new StringBuilder("http://");
sb.append(request.getServerName());
sb.append((request.getServerName().startsWith("127.0.0")?":8080":""));
sb.append("/MyApp/urlToJSP");
return sb.toString();
}
/*
* (non-Javadoc)
* #see main.java.interface.PDFInterface#addImage(
* java.lang.String,
* float,
* float,
* java.lang.String,
* javax.servlet.http.HttpServletRequest,
* float scale
* )
*/
#Override
public void addImage(
String fileName,
float x,
float y,
String name,
HttpServletRequest request
) {
/*
* Here I get the image from a ressource server but you can read the
* image from local storage as well
*/
StringBuilder url = new StringBuilder("http://");
url.append(request.getServerName());
url.append(request.getServerName().startsWith("127.0.0")?":8080":"");
url.append("/MyApp/img/");
url.append(fileName);
try {
ImagePDF image = new ImagePDF(url.toString(), x, y, name, scale);
images.add(image);
}
catch (BadElementException | IOException e) {
System.out.println(Cannot set image for PDF "+url.toString());
}
}
/* (non-Javadoc)
* #see main.java.interface.PDFInterface#getImages()
*/
#Override
public List<ImagePDF> getImages() {
return this.images;
}
/* (non-Javadoc)
* #see main.java.interface.PDFInterface#setParameters(
* CustomObject customObject
* )
*/
#Override
public void setParametres(CustomObject customObject) {
parametres.put(PARAM_1, customObject.getAttribute().toString());
// may have other parameters ...
}
/* (non-Javadoc)
* #see model.bean.ResultatsEcritsPDF#getEncodedQueryString()
*/
#Override
public String getEncodedQueryString() {
/*
* Create the queryString to do further HTTP POST or GET to fetch the
* generated HTML with parameters
*/
StringBuilder queryStringBuilder = new StringBuilder("?");
parameters.entrySet().stream().forEach(e -> {
queryStringBuilder.append(e.getKey());
queryStringBuilder.append("=");
try {
queryStringBuilder.append(
URLEncoder.encode(
e.getValue() == null
? ""
: e.getValue(),
StandardCharsets.UTF_8.name()
)
);
}
catch (UnsupportedEncodingException e1) {
queryStringBuilder.append("");
}
queryStringBuilder.append("&");
});
// Remove the last &
return queryStringBuilder.toString().substring(
0,
queryStringBuilder.toString().length()-1
);
}
/* (non-Javadoc)
* #see model.bean.PDFInterface#getHTMLFile()
*/
#Override
public File getHTMLFile() {
return new File("/path/to/myHTMLFile.html");
}
/* (non-Javadoc)
* #see model.bean.PDFInterface#getPDFFilename()
*/
#Override
public String getPDFFilename() {
return "myPDF.pdf";
}
}
Tell me if it needs some clarification.
EDIT 2020
Things are much simpler now with the improvement of libraries and calling HTTP server itself to generate the dynamic HTML content is not enough simpler and requires additional network configuration in some case.
Here is the new process :
Make a HTML template with CSS2.1 (with <style> tag or inline style=") and include template expressions (EL-style or whatever)
Fetch HTML template as String
Replace template expressions "${ }" in HTML
Replace images in HTML like <img src="image.png" /> by encoded base64 images
Make the PDF file
Write it to response or whatever
Here is the project structure I am using (for example) :
main
|--java
|--bean
|--PdfConverter.java
|--resources
|--pdf
|--template.html
|--img
|--image.png
Dependencies :
<dependency>
<groupId>com.github.librepdf</groupId>
<artifactId>openpdf</artifactId>
<version>1.3.20</version>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-core</artifactId>
<version>9.1.20</version>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf-openpdf</artifactId>
<version>9.1.20</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.9</version>
</dependency>
HTML template (with images) :
<html>
<head>
<style>
body {
font-family:sans-serif;
font-size:14px;
margin: 0 auto;
padding: 0;
}
h1 {
text-align:center;
font-size:21px;
text-transform:capitalize;
}
</style>
</head>
<body>
<h1>some title</h1>
<p>Some paragraph : ${ foo }</p>
<!-- you can style images with CSS! -->
<img src="image.png" style="width:50px;height:50px" />
</body>
</html>
PdfConverter :
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.Map;
import java.util.Scanner;
import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.text.StringSubstitutor;
import org.apache.poi.util.IOUtils;
import org.springframework.http.MediaType;
import org.xhtmlrenderer.pdf.ITextRenderer;
/**
* PdfConverter
* Extends this to implement additional to make the map to replace template
* expressions.
* #author user
* #since 28 juil. 2020
*/
public class PdfConverter {
/**
* Temp directory.
*/
private static final String TMP_DIR =
System.getProperty("java.io.tmpdir") + "/";
/**
* Directory to HTML templates (dedicated to PDF generation).
*/
private static final String PDF_DIR =
"pdf/";
/**
* Directory to the image folders (dedicated to PDF generation).
*/
private static final String PDF_IMG_DIR =
"pdf/img/";
/**
* Prefixes for templates expressions.
*/
private static final String PREFIX_TEMPLATE = "${ ";
/**
* Suffixes for template expressions.
*/
private static final String SUFFIX_TEMPLATE = " }";
/**
* Generated PDF file.
*/
private File generatedPDF;
/**
* PDF file name.
*/
private String pdfName;
/**
* PdfConverter
* #param m map key, value to replace, to replace expressions in HTML
* template.
* #param s ServletContext to get resources from context path.
* #param fileName desired name of the generated PDF.
* #param template name of the HTML template to make the PDF.
* #throws IOExceptio
*/
public PdfConverter(
Map<String, String> m,
ServletContext s,
String fileName,
String template
) throws IOException {
// Set PDF filename
setPdfName(fileName);
// Fetch HTML template
#SuppressWarnings("resource")
String html = new Scanner(
s.getResourceAsStream(PDF_DIR+ template),
StandardCharsets.UTF_8.toString()
).useDelimiter("\\A").next();
/*
* Replace template expressions "${ }" in HTML
*/
StringSubstitutor sub = new StringSubstitutor(
m,
PREFIX_TEMPLATE,
SUFFIX_TEMPLATE
);
String resolvedString = sub.replace(html);
/*
* Replace images like <img src="image.png" /> by
* <img src=\"data:image/png;base64," + base64Image
*/
String[] imgs = StringUtils.substringsBetween(
resolvedString,
"<img src=\"", "\""
);
for (String s1 : imgs) {
String mime = Files.probeContentType(Paths.get(PDF_IMG_DIR + s1));
resolvedString = resolvedString.replace(
s1,
"data:" + mime + ";base64,"
+ Base64.getEncoder().encodeToString(
IOUtils.toByteArray(
s.getResourceAsStream(PDF_IMG_DIR + s1)
)
)
);
}
// Make the PDF file
FileOutputStream fos = new FileOutputStream(TMP_DIR+getPdfName());
ITextRenderer it = new ITextRenderer();
it.setDocumentFromString(resolvedString);
it.layout();
it.createPDF(fos);
fos.close();
// Set the PDF generated file to this PdfConverter instance
setGeneratedPDF(new File(TMP_DIR+getPdfName()));
}
/**
* getGeneratedPDF
*
* #return the generatedPDF
*/
public File getGeneratedPDF() {
return generatedPDF;
}
/**
* setGeneratedPDF
*
* #param generatedPDF the generatedPDF to set
*/
public void setGeneratedPDF(File generatedPDF) {
this.generatedPDF = generatedPDF;
}
/**
* getPdfName
*
* #return the pdfName
*/
public String getPdfName() {
return pdfName;
}
/**
* setPdfName
*
* #param pdfName the pdfName to set
*/
public void setPdfName(String pdfName) {
this.pdfName = pdfName;
}
/**
* writePdfToResponse
* Write the PDF file into the response and delete it from temp directory
* afterwards.
* #param response
* #throws IOException
*/
public void writePdfToResponse(
HttpServletResponse response
) throws IOException {
try (
FileInputStream fis =
new FileInputStream(getGeneratedPDF())
) {
response.setContentType(MediaType.APPLICATION_PDF_VALUE);
response.setHeader(
"Content-Disposition",
"inline; filename=" + getPdfName()
);
response.addHeader(
"Content-Length",
Long.toString(getGeneratedPDF().length())
);
ServletOutputStream servletOutputStream =
response.getOutputStream();
int read = 0;
byte[] bytes = new byte[1024];
while ((read = fis.read(bytes)) != -1) {
servletOutputStream.write(bytes, 0, read);
}
response.flushBuffer();
}
catch (IOException ioe) {
response.setContentType(MediaType.TEXT_PLAIN_VALUE);
response.getWriter().print("Cannot render PDF file.");
response.flushBuffer();
}
finally {
// Delete generated PDF after writing it to the response
getGeneratedPDF().delete();
}
}
}
And how to use it in servlet (Spring MVC example) :
/**
* downloadPDF
*
* #param response
* #param foo
* #throws IOException
*/
#PostMapping("/downloadPDF")
public void downloadPDF(
HttpServletRequest request,
HttpServletResponse response,
String foo
) throws IOException {
Map<String, String> m = new HashMap<>();
m.put("foo", "my_foo_value");
PdfConverter pdfConverter = new PdfConverter(
m,
request.getServletContext(),
"my_pdf",
"template"
);
pdfConverter.writePdfToResponse(response);
}
I tried reading google tutorials and doing the YouTube Analytics Api example. But, I am unable to make the code. Can someone help me to make it (using Java and Eclipse) ?
it shows an error in Import file
import com.google.api.services.youtube.YouTube;
import com.google.api.services.youtube.model.Channel;
import com.google.api.services.youtube.model.ChannelListResponse;
import com.google.api.services.youtubeAnalytics.YoutubeAnalytics;
import com.google.api.services.youtubeAnalytics.model.ResultTable;
import com.google.api.services.youtubeAnalytics.model.ResultTable.ColumnHeaders;
import com.google.common.collect.Lists;
Example :
package com.google.api.services.samples.youtube.cmdline.youtube_analytics_cmdline_report_sample;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.math.BigDecimal;
import java.util.List;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.java6.auth.oauth2.FileCredentialStore;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.youtube.YouTube;
import com.google.api.services.youtube.model.Channel;
import com.google.api.services.youtube.model.ChannelListResponse;
import com.google.api.services.youtubeAnalytics.YoutubeAnalytics;
import com.google.api.services.youtubeAnalytics.model.ResultTable;
import com.google.api.services.youtubeAnalytics.model.ResultTable.ColumnHeaders;
import com.google.common.collect.Lists;
public class Samp {
/**
* Demo displaying YouTube metrics from a user's channel using the YouTube Data and YouTube
* Analytics APIs. It also uses OAuth2 for authorization.
*
* #author Christoph Schwab-Ganser and Jeremy Walker
*/
public class YouTubeAnalyticsReports {
/** Global instance of the HTTP transport. */
private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
/** Global instance of the JSON factory. */
private static final JsonFactory JSON_FACTORY = new JacksonFactory();
/** Global instance of Youtube object to make general YouTube API requests. */
private static YouTube youtube;
/** Global instance of YoutubeAnalytics object to make analytic API requests. */
private static YoutubeAnalytics analytics;
/**
* Authorizes the installed application to access user's protected YouTube data.
*
* #param scopes list of scopes needed to access general and analytic YouTube info.
*/
private static Credential authorize(List<String> scopes) throws Exception {
// Load client secrets.
GoogleClientSecrets clientSecrets =
GoogleClientSecrets.load(
JSON_FACTORY,
YouTubeAnalyticsReports.class.getResourceAsStream("/client_secrets.json"));
// Checks that the defaults have been replaced (Default = "Enter X here").
if (clientSecrets.getDetails().getClientId().startsWith("Enter")
|| clientSecrets.getDetails().getClientSecret().startsWith("Enter ")) {
System.err.println(
"Enter Client ID and Secret from https://code.google.com/apis/console/?api=youtube"
+ "into youtube-analytics-cmdline-report-sample/src/main/resources/client_secrets.json");
System.exit(1);
}
// Set up file credential store.
FileCredentialStore credentialStore =
new FileCredentialStore(
new File(System.getProperty("user.home"),
".credentials/youtube-analytics-api-report.json"),
JSON_FACTORY);
// Set up authorization code flow.
GoogleAuthorizationCodeFlow flow =
new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT,
JSON_FACTORY,
clientSecrets,
scopes)
.setCredentialStore(credentialStore).build();
// Authorize.
return new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
}
/**
* Authorizes user, gets user's default channel via YouTube Data API, and gets/prints stats on
* user's channel using the YouTube Analytics API.
*
* #param args command line args (not used).
*/
public static void main(String[] args) {
// Scopes required to access YouTube general and analytics information.
List<String> scopes = Lists.newArrayList(
"https://www.googleapis.com/auth/yt-analytics.readonly",
"https://www.googleapis.com/auth/youtube.readonly"
);
try {
Credential credential = authorize(scopes);
// YouTube object used to make all non-analytic API requests.
youtube = new YouTube.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName("youtube-analytics-api-report-example")
.build();
// YouTube object used to make all analytic API requests.
analytics = new YoutubeAnalytics.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName("youtube-analytics-api-report-example")
.build();
// Constructs request to get channel id for current user.
YouTube.Channels.List channelRequest = youtube.channels().list("id,snippet");
channelRequest.setMine(true);
channelRequest.setFields("items(id,snippet/title)");
ChannelListResponse channels = channelRequest.execute();
// List of channels associated with user.
List<Channel> listOfChannels = channels.getItems();
// Grab default channel which is always the first item in the list.
Channel defaultChannel = listOfChannels.get(0);
String channelId = defaultChannel.getId();
PrintStream writer = System.out;
if (channelId == null) {
writer.println("No channel found.");
} else {
writer.println("Default Channel: " + defaultChannel.getSnippet().getTitle() +
" ( " + channelId + " )\n");
printData(writer, "Views Over Time.", executeViewsOverTimeQuery(analytics, channelId));
printData(writer, "Top Videos", executeTopVideosQuery(analytics, channelId));
printData(writer, "Demographics", executeDemographicsQuery(analytics, channelId));
}
} catch (IOException e) {
System.err.println("IOException: " + e.getMessage());
e.printStackTrace();
} catch (Throwable t) {
System.err.println("Throwable: " + t.getMessage());
t.printStackTrace();
}
}
/**
* Returns the views and unique viewers per day.
*
* #param analytics the analytics service object used to access the API.
* #param id the string id from which to retrieve data.
* #return the response from the API.
* #throws IOException if an API error occurred.
*/
private static ResultTable executeViewsOverTimeQuery(YoutubeAnalytics analytics,
String id) throws IOException {
return analytics.reports()
.query("channel==" + id, // channel id
"2012-01-01", // Start date.
"2012-01-14", // End date.
"views,uniques") // Metrics.
.setDimensions("day")
.setSort("day")
.execute();
}
/**
* Returns the top video by views.
*
* #param analytics the analytics service object used to access the API.
* #param id the string id from which to retrieve data.
* #return the response from the API.
* #throws IOException if an API error occurred.
*/
private static ResultTable executeTopVideosQuery(YoutubeAnalytics analytics,
String id) throws IOException {
return analytics.reports()
.query("channel==" + id, // channel id
"2012-01-01", // Start date.
"2012-08-14", // End date.
"views,subscribersGained,subscribersLost") // Metrics.
.setDimensions("video")
.setSort("-views")
.setMaxResults(10)
.execute();
}
/**
* Returns the demographics report
*
* #param analytics the analytics service object used to access the API.
* #param id the string id from which to retrieve data.
* #return the response from the API.
* #throws IOException if an API error occurred.
*/
private static ResultTable executeDemographicsQuery(YoutubeAnalytics analytics,
String id) throws IOException {
return analytics.reports()
.query("channel==" + id, // channel id
"2007-01-01", // Start date.
"2012-08-14", // End date.
"viewerPercentage") // Metrics.
.setDimensions("ageGroup,gender")
.setSort("-viewerPercentage")
.execute();
}
/**
* Prints the output from the API. The channel name is printed along with
* each column name and all the data in the rows.
* #param writer stream to output to
* #param title title of the report
* #param results data returned from the API.
*/
private static void printData(PrintStream writer, String title, ResultTable results) {
writer.println("Report: " + title);
if (results.getRows() == null || results.getRows().isEmpty()) {
writer.println("No results Found.");
} else {
// Print column headers.
for (ColumnHeaders header : results.getColumnHeaders()) {
writer.printf("%30s", header.getName());
}
writer.println();
// Print actual data.
for (List<Object> row : results.getRows()) {
for (int colNum = 0; colNum < results.getColumnHeaders().size(); colNum++) {
ColumnHeaders header = results.getColumnHeaders().get(colNum);
Object column = row.get(colNum);
if ("INTEGER".equals(header.getUnknownKeys().get("dataType"))) {
long l = ((BigDecimal) column).longValue();
writer.printf("%30d", l);
} else if ("FLOAT".equals(header.getUnknownKeys().get("dataType"))) {
writer.printf("%30f", column);
} else if ("STRING".equals(header.getUnknownKeys().get("dataType"))) {
writer.printf("%30s", column);
} else {
// default output.
writer.printf("%30s", column);
}
}
writer.println();
}
writer.println();
}
}
}
}
It would be helpful if you could state what error do you see in Imports?
But assuming you are finding errors in Imports it means you are missing project dependencies in your project path. Find the dependencies in Maven POM.xml. If you are not using Maven to build your project, then please download all the dependent JAR files as mentioned in POM.xml
While trying to run the code bellow to gain a SAML token (taken from VMWare samples to authenticate with SSO server) I got the following exception.
From some reason the request version 'http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue' and namespace 'http://docs.oasis-open.org/ws-sx/ws-trust/200512' are not supported.
Appreciate your help...
Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: Request version 'http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue' and namespace 'http://docs.oasis-open.org/ws-sx/ws-trust/200512' are not supported
at com.sun.xml.internal.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:178)
at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:125)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:108)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:78)
at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:135)
at com.sun.proxy.$Proxy40.issue(Unknown Source)
at com.vmware.sso.client.samples.AcquireBearerTokenByUserCredentialSample.getToken(AcquireBearerTokenByUserCredentialSample.java:178)
at com.vmware.sso.client.samples.AcquireBearerTokenByUserCredentialSample.main(AcquireBearerTokenByUserCredentialSample.java:210)
package com.vmware.sso.client.samples;
import java.util.GregorianCalendar;
import java.util.Map;
import java.util.TimeZone;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.ws.BindingProvider;
import org.oasis_open.docs.ws_sx.ws_trust._200512.LifetimeType;
import org.oasis_open.docs.ws_sx.ws_trust._200512.RenewingType;
import org.oasis_open.docs.ws_sx.ws_trust._200512.RequestSecurityTokenType;
import org.oasis_open.docs.wss._2004._01.oasis_200401_wss_wssecurity_utility_1_0.AttributedDateTime;
import org.w3c.dom.Element;
import com.rsa.names._2009._12.product.riat.wsdl.STSService;
import com.rsa.names._2009._12.product.riat.wsdl.STSServicePortType;
import com.vmware.sso.client.soaphandlers.HeaderHandlerResolver;
import com.vmware.sso.client.soaphandlers.SamlTokenExtractionHandler;
import com.vmware.sso.client.soaphandlers.TimeStampHandler;
import com.vmware.sso.client.soaphandlers.UserCredentialHandler;
import com.vmware.sso.client.utils.Utils;
/**
* This sample illustrates acquiring a bearer token from SSO server by passing
* the username and password of the user
*
* <pre>
* <b>Usage:</b>
* run.bat com.vmware.sso.client.samples.AcquireBearerTokenByUserCredentialSample [sso url] [username] [password]
* </pre>
*
* #author Ecosystem Engineering
*/
public class AcquireBearerTokenByUserCredentialSample {
/**
* #param args
* {#link String} array containing the following values in the
* below order: <li>SSO server url e.g. https://[Host Name or IP
* Address]:8444/ims/STSService</li> <li>username</li> <li>
* password</li>
* #return {#link Element} representing the Token issued
* #throws DatatypeConfigurationException
*/
public static Element getToken(String[] args)
throws DatatypeConfigurationException {
/* Instantiating the STSService */
STSService stsService = new STSService();
/*
* Instantiating the HeaderHandlerResolver. This is required to provide
* the capability of modifying the SOAP headers and the SOAP message in
* general for various requests via the different handlers. For
* different kinds of requests to SSO server one needs to follow the
* WS-Trust guidelines to provide the required SOAP message structure.
*/
HeaderHandlerResolver headerResolver = new HeaderHandlerResolver();
/*
* For this specific case we need the following header elements wrapped
* in the security tag.
*
* 1. Timestamp containing the request's creation and expiry time
*
* 2. UsernameToken containing the username/password
*/
/* Adding the Timestamp via TimeStampHandler */
headerResolver.addHandler(new TimeStampHandler());
/* Adding the UsernameToken via UserCredentialHandler */
UserCredentialHandler ucHandler = new UserCredentialHandler(args[1],
args[2]);
SamlTokenExtractionHandler sbHandler = new SamlTokenExtractionHandler();
headerResolver.addHandler(ucHandler);
headerResolver.addHandler(sbHandler);
/*
* Set the handlerResolver for the STSService to the
* HeaderHandlerResolver created above
*/
stsService.setHandlerResolver(headerResolver);
/*
* Retrieve the STSServicePort from the STSServicePortType object Note:
* All the required handlerResolvers need to be set in the
* STSServicePortType object before you retrieve the STSService instance
*/
STSServicePortType stsPort = stsService.getSTSServicePort();
/*
* Construct the SOAP body for the request. RequestSecurityTokenType is
* the parameter type that is passed to the "acquire" method. However,
* based on what kind of token (bearer or holder-of-key type) and by
* what means (aka username/password, certificate, or existing token) we
* want to acquire the token, different elements need to be populated
*/
RequestSecurityTokenType tokenType = new RequestSecurityTokenType();
/*
* For this request we need at least the following element in the
* RequestSecurityTokenType set
*
* 1. Lifetime - represented by LifetimeType which specifies the
* lifetime for the token to be issued
*
* 2. Tokentype - "urn:oasis:names:tc:SAML:2.0:assertion", which is the
* class that models the requested token
*
* 3. RequestType -
* "http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue", as we want
* to get a token issued
*
* 4. KeyType -
* "http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer",
* representing the kind of key the token will have. There are two
* options namely bearer and holder-of-key
*
* 5. SignatureAlgorithm -
* "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", representing the
* algorithm used for generating signature
*
* 6. Renewing - represented by the RenewingType which specifies whether
* the token is renewable or not
*/
LifetimeType lifetime = new LifetimeType();
DatatypeFactory dtFactory = DatatypeFactory.newInstance();
GregorianCalendar cal = new GregorianCalendar(
TimeZone.getTimeZone("GMT"));
XMLGregorianCalendar xmlCalendar = dtFactory
.newXMLGregorianCalendar(cal);
AttributedDateTime created = new AttributedDateTime();
created.setValue(xmlCalendar.toXMLFormat());
AttributedDateTime expires = new AttributedDateTime();
xmlCalendar.add(dtFactory.newDuration(30 * 60 * 1000));
expires.setValue(xmlCalendar.toXMLFormat());
lifetime.setCreated(created);
lifetime.setExpires(expires);
tokenType.setTokenType("urn:oasis:names:tc:SAML:2.0:assertion");
tokenType
.setRequestType("http://docs.oasis-open.org/ws-sx/ws-trust/200512/Issue");
tokenType.setLifetime(lifetime);
tokenType
.setKeyType("http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer");
tokenType
.setSignatureAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
RenewingType renewing = new RenewingType();
renewing.setAllow(Boolean.FALSE);
renewing.setOK(Boolean.FALSE); // WS-Trust Profile: MUST be set to false
tokenType.setRenewing(renewing);
/* Set the endpoint address for the request */
Map<String, Object> reqContext = ((BindingProvider) stsPort)
.getRequestContext();
reqContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, args[0]);
/*
* Invoke the "issue" method on the STSService object to acquire the
* token from SSO Server
*/
stsPort.issue(tokenType);
// SamlTokenExtractionHandler will now contain the raw SAML token for
// further consumption
return sbHandler.getToken();
}
private static void printUsage() {
System.out
.println("run.bat com.vmware.sso.client.samples.AcquireBearerTokenByUserCredentialSample [sso url] [username] [password]");
}
public static void main(String[] args)
throws DatatypeConfigurationException {
if (args.length < 3) {
printUsage();
return;
}
HostnameVerifier hv = new HostnameVerifier() {
#Override
public boolean verify(String urlHostName, SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(hv);
Utils.trustAllHttpsCertificates();
System.out.println("Aquiring a bearer token by using user credentials");
Utils.printToken(getToken(args));
}
}
The reason I got the error was pointing the wrong SSO URL
The right address is
https://SSO-SERVER:7444/ims/STSService
I was looking for a Chrome Extension which can intercept the download whenever we click on a PDF link or on a link that spawns a PDF at server end programmatically. One way of doing it was Selenium Browser Profiling, I found this particular code. I want Selenium to download the PDF file and rename it according to the strings i pass from the JAVA program.
How can i use this code to download code and hook it up it with my program. It should trigger this whenever i execute a command like this:-
**driver.findElement(By.xpath("//a[contains(#href,\"/bbtobs/bbtolbext/statements/savepdf?type=current&AccountIndex=0\")]")).click();**
CODE-
package com.lazerycode.selenium.filedownloader;
import org.apache.commons.io.FileUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.log4j.Logger;
import org.openqa.selenium.Cookie;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Set;
public class FileDownloader {
private static final Logger LOG = Logger.getLogger(FileDownloader.class);
private WebDriver driver;
private String localDownloadPath = System.getProperty("java.io.tmpdir");
private boolean followRedirects = true;
private boolean mimicWebDriverCookieState = true;
private int httpStatusOfLastDownloadAttempt = 0;
public FileDownloader(WebDriver driverObject) {
this.driver = driverObject;
}
/**
* Specify if the FileDownloader class should follow redirects when trying to download a file
*
* #param value
*/
public void followRedirectsWhenDownloading(boolean value) {
this.followRedirects = value;
}
/**
* Get the current location that files will be downloaded to.
*
* #return The filepath that the file will be downloaded to.
*/
public String localDownloadPath() {
return this.localDownloadPath;
}
/**
* Set the path that files will be downloaded to.
*
* #param filePath The filepath that the file will be downloaded to.
*/
public void localDownloadPath(String filePath) {
this.localDownloadPath = filePath;
}
/**
* Download the file specified in the href attribute of a WebElement
*
* #param element
* #return
* #throws Exception
*/
public String downloadFile(WebElement element) throws Exception {
return downloader(element, "href");
}
/**
* Download the image specified in the src attribute of a WebElement
*
* #param element
* #return
* #throws Exception
*/
public String downloadImage(WebElement element) throws Exception {
return downloader(element, "src");
}
/**
* Gets the HTTP status code of the last download file attempt
*
* #return
*/
public int getHTTPStatusOfLastDownloadAttempt() {
return this.httpStatusOfLastDownloadAttempt;
}
/**
* Mimic the cookie state of WebDriver (Defaults to true)
* This will enable you to access files that are only available when logged in.
* If set to false the connection will be made as an anonymouse user
*
* #param value
*/
public void mimicWebDriverCookieState(boolean value) {
this.mimicWebDriverCookieState = value;
}
/**
* Load in all the cookies WebDriver currently knows about so that we can mimic the browser cookie state
*
* #param seleniumCookieSet
* #return
*/
private BasicCookieStore mimicCookieState(Set seleniumCookieSet) {
BasicCookieStore mimicWebDriverCookieStore = new BasicCookieStore();
for (Cookie seleniumCookie : seleniumCookieSet) {
BasicClientCookie duplicateCookie = new BasicClientCookie(seleniumCookie.getName(), seleniumCookie.getValue());
duplicateCookie.setDomain(seleniumCookie.getDomain());
duplicateCookie.setSecure(seleniumCookie.isSecure());
duplicateCookie.setExpiryDate(seleniumCookie.getExpiry());
duplicateCookie.setPath(seleniumCookie.getPath());
mimicWebDriverCookieStore.addCookie(duplicateCookie);
}
return mimicWebDriverCookieStore;
}
/**
* Perform the file/image download.
*
* #param element
* #param attribute
* #return
* #throws IOException
* #throws NullPointerException
*/
private String downloader(WebElement element, String attribute) throws IOException, NullPointerException, URISyntaxException {
String fileToDownloadLocation = element.getAttribute(attribute);
if (fileToDownloadLocation.trim().equals("")) throw new NullPointerException("The element you have specified does not link to anything!");
URL fileToDownload = new URL(fileToDownloadLocation);
File downloadedFile = new File(this.localDownloadPath + fileToDownload.getFile().replaceFirst("/|\\\\", ""));
if (downloadedFile.canWrite() == false) downloadedFile.setWritable(true);
HttpClient client = new DefaultHttpClient();
BasicHttpContext localContext = new BasicHttpContext();
LOG.info("Mimic WebDriver cookie state: " + this.mimicWebDriverCookieState);
if (this.mimicWebDriverCookieState) {
localContext.setAttribute(ClientContext.COOKIE_STORE, mimicCookieState(this.driver.manage().getCookies()));
}
HttpGet httpget = new HttpGet(fileToDownload.toURI());
HttpParams httpRequestParameters = httpget.getParams();
httpRequestParameters.setParameter(ClientPNames.HANDLE_REDIRECTS, this.followRedirects);
httpget.setParams(httpRequestParameters);
LOG.info("Sending GET request for: " + httpget.getURI());
HttpResponse response = client.execute(httpget, localContext);
this.httpStatusOfLastDownloadAttempt = response.getStatusLine().getStatusCode();
LOG.info("HTTP GET request status: " + this.httpStatusOfLastDownloadAttempt);
LOG.info("Downloading file: " + downloadedFile.getName());
FileUtils.copyInputStreamToFile(response.getEntity().getContent(), downloadedFile);
response.getEntity().getContent().close();
String downloadedFileAbsolutePath = downloadedFile.getAbsolutePath();
LOG.info("File downloaded to '" + downloadedFileAbsolutePath + "'");
return downloadedFileAbsolutePath;
}
}
String s = driver.findElement(By.cssSelector("#navbtm img")).getAttribute("src");
URL url = new URL(s);
System.out.println(url);
BufferedImage bufImgOne = ImageIO.read(url);
ImageIO.write(bufImgOne, "png", new File("test.png"));
I have found an excellent article about it. Tried, and works perfectly:
http://ardesco.lazerycode.com/index.php/2012/07/how-to-download-files-with-selenium-and-why-you-shouldnt/
UPDATE:
Better solution is to get the image from the browser itself:
https://groups.google.com/forum/#!msg/selenium-users/8atiPIh39OY/Gp9_KEXnpRUJ
I have a problem with MySQL and Postgresql9.2 this is the problem :
org.apache.lucene.store.jdbc.JdbcStoreException: Failed to execute sql [insert into LUCENE_INDEX_TABLE (name_, value_, size_, lf_, deleted_) values ( ?, ?, ?, current_timestamp, ? )]; nested exception is org.postgresql.util.PSQLException: Les Large Objects ne devraient pas être utilisés en mode auto-commit.
org.postgresql.util.PSQLException: Les Large Objects ne devraient pas être utilisés en mode auto-commit.
at org.postgresql.largeobject.LargeObjectManager.createLO(LargeObjectManager.java:239)
at org.postgresql.largeobject.LargeObjectManager.createLO(LargeObjectManager.java:226)
at org.postgresql.jdbc2.AbstractJdbc2Statement.setBlob(AbstractJdbc2Statement.java:3048)
at org.apache.lucene.store.jdbc.index.AbstractJdbcIndexOutput$1.fillPrepareStatement(AbstractJdbcIndexOutput.java:55)
at org.apache.lucene.store.jdbc.support.JdbcTemplate.executeUpdate(JdbcTemplate.java:174)
at org.apache.lucene.store.jdbc.index.AbstractJdbcIndexOutput.close(AbstractJdbcIndexOutput.java:47)
at org.apache.lucene.store.jdbc.index.RAMAndFileJdbcIndexOutput.close(RAMAndFileJdbcIndexOutput.java:81)
at org.apache.lucene.util.IOUtils.close(IOUtils.java:141)
at org.apache.lucene.index.FieldsWriter.close(FieldsWriter.java:139)
at org.apache.lucene.index.StoredFieldsWriter.flush(StoredFieldsWriter.java:55)
at org.apache.lucene.index.DocFieldProcessor.flush(DocFieldProcessor.java:59)
at org.apache.lucene.index.DocumentsWriter.flush(DocumentsWriter.java:581)
at org.apache.lucene.index.IndexWriter.doFlush(IndexWriter.java:3587)
at org.apache.lucene.index.IndexWriter.prepareCommit(IndexWriter.java:3376)
at org.apache.lucene.index.IndexWriter.commitInternal(IndexWriter.java:3485)
at org.apache.lucene.index.IndexWriter.commit(IndexWriter.java:3467)
at org.apache.lucene.index.IndexWriter.commit(IndexWriter.java:3451)
at test.lucene.chaima.JDBCIndexer.addIndex(JDBCIndexer.java:137)
at test.lucene.chaima.JDBCIndexer.index(JDBCIndexer.java:92)
at test.lucene.chaima.JDBCIndexer.createAndBuildIndex(JDBCIndexer.java:78)
at test.lucene.chaima.JDBCIndexer.buildIndex(JDBCIndexer.java:69)
at test.lucene.chaima.JDBCIndexer.main(JDBCIndexer.java:172)
org.apache.lucene.store.jdbc.JdbcStoreException: Failed to execute sql [insert into LUCENE_INDEX_TABLE (name_, value_, size_, lf_, deleted_) values ( ?, ?, ?, current_timestamp, ? )]; nested exception is org.postgresql.util.PSQLException: Les Large Objects ne devraient pas être utilisés en mode auto-commit.
org.postgresql.util.PSQLException: Les Large Objects ne devraient pas être utilisés en mode auto-commit.
at org.postgresql.largeobject.LargeObjectManager.createLO(LargeObjectManager.java:239)
at org.postgresql.largeobject.LargeObjectManager.createLO(LargeObjectManager.java:226)
at org.postgresql.jdbc2.AbstractJdbc2Statement.setBlob(AbstractJdbc2Statement.java:3048)
at org.apache.lucene.store.jdbc.index.AbstractJdbcIndexOutput$1.fillPrepareStatement(AbstractJdbcIndexOutput.java:55)
at org.apache.lucene.store.jdbc.support.JdbcTemplate.executeUpdate(JdbcTemplate.java:174)
at org.apache.lucene.store.jdbc.index.AbstractJdbcIndexOutput.close(AbstractJdbcIndexOutput.java:47)
at org.apache.lucene.store.jdbc.index.RAMAndFileJdbcIndexOutput.close(RAMAndFileJdbcIndexOutput.java:81)
at org.apache.lucene.store.ChecksumIndexOutput.close(ChecksumIndexOutput.java:61)
at org.apache.lucene.index.SegmentInfos.finishCommit(SegmentInfos.java:863)
at org.apache.lucene.index.IndexWriter.finishCommit(IndexWriter.java:3501)
at org.apache.lucene.index.IndexWriter.commitInternal(IndexWriter.java:3490)
at org.apache.lucene.index.IndexWriter.closeInternal(IndexWriter.java:1873)
at org.apache.lucene.index.IndexWriter.close(IndexWriter.java:1812)
at org.apache.lucene.index.IndexWriter.close(IndexWriter.java:1776)
at test.lucene.chaima.JDBCIndexer.index(JDBCIndexer.java:102)
at test.lucene.chaima.JDBCIndexer.createAndBuildIndex(JDBCIndexer.java:78)
at test.lucene.chaima.JDBCIndexer.buildIndex(JDBCIndexer.java:69)
at test.lucene.chaima.JDBCIndexer.main(JDBCIndexer.java:172)
org.apache.lucene.index.IndexNotFoundException: no segments* file found in test.lucene.chaima.MyJDBCDirectory#9506dc4 lockFactory=null: files: [write.lock]
at org.apache.lucene.index.SegmentInfos$FindSegmentsFile.run(SegmentInfos.java:667)
at org.apache.lucene.index.DirectoryReader.open(DirectoryReader.java:72)
at org.apache.lucene.index.IndexReader.open(IndexReader.java:256)
at test.lucene.chaima.JDBCSearcher.search(JDBCSearcher.java:56)
at test.lucene.chaima.JDBCIndexer.buildIndex(JDBCIndexer.java:70)
at test.lucene.chaima.JDBCIndexer.main(JDBCIndexer.java:172)
i found many solution but no one solve my problem
please i need the solution if any one can help me
thanks.
I put here the source code of my application : i have 3 classes
MyJDBCDirectory.java
package test.lucene.chaima;
import java.io.IOException;
import javax.sql.DataSource;
import org.apache.lucene.store.jdbc.JdbcDirectory;
import org.apache.lucene.store.jdbc.JdbcDirectorySettings;
import org.apache.lucene.store.jdbc.JdbcStoreException;
import org.apache.lucene.store.jdbc.dialect.Dialect;
import org.apache.lucene.store.jdbc.support.JdbcTable;
/**
* The Class MyJDBCDirectory.
*
* #author prabhat.jha
*/
public class MyJDBCDirectory extends JdbcDirectory {
/**
* Instantiates a new my jdbc directory.
*
* #param dataSource
* the data source
* #param dialect
* the dialect
* #param settings
* the settings
* #param tableName
* the table name
*/
public MyJDBCDirectory(DataSource dataSource, Dialect dialect, JdbcDirectorySettings settings, String tableName) {
super(dataSource, dialect, settings, tableName);
}
/**
* Instantiates a new my jdbc directory.
*
* #param dataSource the data source
* #param dialect the dialect
* #param tableName the table name
*/
public MyJDBCDirectory(DataSource dataSource, Dialect dialect, String tableName) {
super(dataSource, dialect, tableName);
}
/**
* Instantiates a new my jdbc directory.
*
* #param dataSource the data source
* #param settings the settings
* #param tableName the table name
* #throws JdbcStoreException the jdbc store exception
*/
public MyJDBCDirectory(DataSource dataSource, JdbcDirectorySettings settings, String tableName) throws JdbcStoreException {
super(dataSource, settings, tableName);
}
/**
* Instantiates a new my jdbc directory.
*
* #param dataSource the data source
* #param table the table
*/
public MyJDBCDirectory(DataSource dataSource, JdbcTable table) {
super(dataSource, table);
}
/**
* Instantiates a new my jdbc directory.
*
* #param dataSource the data source
* #param tableName the table name
* #throws JdbcStoreException the jdbc store exception
*/
public MyJDBCDirectory(DataSource dataSource, String tableName) throws JdbcStoreException {
super(dataSource, tableName);
}
/**
* (non-Javadoc).
*
* #return the string[]
* #throws IOException Signals that an I/O exception has occurred.
* #see org.apache.lucene.store.Directory#listAll()
*/
#Override
public String[] listAll() throws IOException {
return super.list();
}
}
JDBCDatabaseUtil.java
package test.lucene.chaima;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.postgresql.ds.PGPoolingDataSource;
import org.postgresql.ds.PGSimpleDataSource;
//import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
/**
* The Class JDBCDatabaseUtil.
* #author prabhat.jha
*/
public class JDBCDatabaseUtil {
/**
* Gets the data source.
*
* #return the data source
*/
public static DataSource getDataSource() {
PGSimpleDataSource dataSource = new PGSimpleDataSource();
dataSource.setUser("postgres");
dataSource.setPassword("root");
dataSource.setDatabaseName("postgres");
/*MysqlDataSource dataSource = new MysqlDataSource();
dataSource.setUser("root");
dataSource.setPassword("root");
dataSource.setEmulateLocators(true);
dataSource.setUrl("jdbc:mysql://localhost:3306/lucene?emulateLocators=true&useUnicode=true&characterEncoding=UTF-8&useFastDateParsing=false");
*/
return dataSource;
}
/**
* Gets the connection.
*
* #return the connection
* #throws SQLException
* the sQL exception
*/
public static Connection getConnection() throws SQLException {
//getDataSource().getConnection().setAutoCommit(false);
return getDataSource().getConnection();
}
}
JDBCIndexer.java
package test.lucene.chaima;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.SimpleAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.store.jdbc.JdbcDirectory;
import org.apache.lucene.store.jdbc.dialect.PostgreSQLDialect;
import org.apache.lucene.util.Version;
/**
* The Class JDBCIndexer.
*
* #author chaima
*/
public class JDBCIndexer {
/** The jdbc directory. */
private Directory jdbcDirectory = null;
/**
* Instantiates a new jDBC indexer.
*
* #param jdbcDirectory
* the jdbc directory
*/
public JDBCIndexer(Directory jdbcDirectory) {
super();
this.jdbcDirectory = jdbcDirectory;
}
/**
* Gets the jdbc directory.
*
* #return the jdbc directory
*/
public Directory getJdbcDirectory() {
if (jdbcDirectory == null) {
throw new IllegalStateException("Index not yet build, rerun indexing");
}
return jdbcDirectory;
}
/**
* Sets the jdbc directory.
*
* #param jdbcDirectory
* the new jdbc directory
*/
public void setJdbcDirectory(Directory jdbcDirectory) {
this.jdbcDirectory = jdbcDirectory;
}
/**
* Builds the index.
*/
public void buildIndex() {
createAndBuildIndex();
}
/**
* Creates the and build index.
*/
private void createAndBuildIndex() {
createIndexTable();
index();
}
/**
* Index.
*/
private void index() {
Analyzer analyzer = new SimpleAnalyzer(Version.LUCENE_36);
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_36, analyzer);
IndexWriter indexWriter = null;
try {
indexWriter = new IndexWriter(getJdbcDirectory(), analyzer,true, IndexWriter.MaxFieldLength.UNLIMITED);
Boolean locked=indexWriter.isLocked(jdbcDirectory);
addIndex(indexWriter);
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (LockObtainFailedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (indexWriter != null) {
try {
indexWriter.close();
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
indexWriter = null;
}
}
}
}
/**
*
*
* #param indexWriter
* the index writer
*/
private void addIndex(IndexWriter indexWriter) throws CorruptIndexException, IOException {
try {
Connection connection = JDBCDatabaseUtil.getConnection();
connection.setAutoCommit(false);
String query = "SELECT id, name, lastname FROM users";
PreparedStatement pstmt = connection.prepareStatement(query);
ResultSet resultSet = pstmt.executeQuery();
while (resultSet.next()) {
Document document = new Document();
document.add(new Field("id", String.valueOf(resultSet.getInt(1)), Field.Store.YES, Field.Index.ANALYZED));
document.add(new Field("name", String.valueOf(resultSet.getString(2)), Field.Store.YES, Field.Index.ANALYZED));
document.add(new Field("lastname", String.valueOf(resultSet.getString(3)), Field.Store.YES, Field.Index.ANALYZED));
indexWriter.addDocument(document);
indexWriter.commit();
}
indexWriter.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* Creates the index table.
*/
private void createIndexTable() {
if (this.jdbcDirectory == null) {
setJdbcDirectory(new MyJDBCDirectory(JDBCDatabaseUtil.getDataSource(), new PostgreSQLDialect(), "LUCENE_INDEX_TABLE"));
}
try {
/**
* No need to manually create index table, create method will
* automatically create it.
*/
boolean existe= ((JdbcDirectory) getJdbcDirectory()).tableExists();
if(existe)
System.out.println("table existe");
else{
System.out.println("table non existe");
((JdbcDirectory) getJdbcDirectory()).create();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new JDBCIndexer(null).buildIndex();
}
}
and the table users :
CREATE TABLE users
(
id integer NOT NULL,
name character(20),
lastname character(20),
CONSTRAINT pk_id PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
ALTER TABLE users
OWNER TO postgres;
and the jars :
commons-logging-1.0.4.jar
compass-2.2.0.jar
lucene-core-3.6.1.jar
postgresql-9.2-1002.jdbc4.jar
I have created my own JdbcDirectory implementation, though it would rely on JEE6 to take advantage of the #Singleton annotation. The code itself isn't too trivial to paste into a StackOverflow post and it still has a few limitations. Key part being you cannot do multiple operations on a single transaction using multiple threads because of the database locking semantics.
https://github.com/trajano/doxdb/tree/jdbc-directory-example/doxdb-ejb/src/main/java/net/trajano/doxdb/search/lucene
Looking at your implementation, it seems like you're also keeping the deleted "files" probably because it would have less fragmentation on the database store, whereas mine I had removed the record itself.
I have tagged a version that I am working with which seems stable enough for my test loads. Feel free to make comments or suggestions on it.
Compass is defunct, and I believe the last version of Lucene supported by it, explicitly, is 2.4.1.
I'd recommend you either upgrade to ElasticSearch, or downgrade Lucene.
You could also take a look at this blog post: "Create Lucene Index in database using JdbcDirectory", which attempts to create a version of JdbcDirectory compatible with Lucene 3.6. It would likely be much better to avoid JdbcDirectory all together.