How to use itext to span 2 columnns of a page? - itext

I am trying to do the following using itext and java through eclipse.I need to create a PDF which will consist of a no of multiple choice questions retrieved from database.The data retrieved is in the form of html tags hence for that i am using xml worker to parse it.I am able to retrieve the questions one by one from the database and add it to the pdf.But the problem is that it occupies only one side of a page while i need the questions to cover 2 columns of a page.
When the end of the first PDF page is reached it should utilize the right hand corner of the first PDF page to add questions.Only when both left and right sides of a page are fully used it should move on to the next PDF page.
Now i managed to get the html data in 2 columns using ColumnText.But the problem i face now is that the questions retrieved from database do not appear in the format as intended.Each question is getting displayed on one line.
I entered the questions is this format:
1)What is 2+2=?
a)2
b)4
c)8
d)15
I want that the output on pdf should be as above.
However i get the following as output:
1)What is2+2=?a)2b)4c)8d)15
How do i preserve the html formatting ?????????
This is my code so far:
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.List;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.draw.LineSeparator;
import com.itextpdf.tool.xml.ElementHandler;
import com.itextpdf.tool.xml.ElementList;
import com.itextpdf.tool.xml.Pipeline;
import com.itextpdf.tool.xml.Writable;
import com.itextpdf.tool.xml.XMLWorker;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import com.itextpdf.tool.xml.html.Tags;
import com.itextpdf.tool.xml.parser.XMLParser;
import com.itextpdf.tool.xml.pipeline.WritableElement;
import com.itextpdf.tool.xml.pipeline.css.CSSResolver;
import com.itextpdf.tool.xml.pipeline.css.CssResolverPipeline;
import com.itextpdf.tool.xml.pipeline.end.PdfWriterPipeline;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipeline;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipelineContext;
public class ColumnTextExample {
public static final float[][] COLUMNS = {
{ 36, 36, 224, 579 } , { 230, 36, 418, 579 }
};
public static void main(String[] args)throws IOException, DocumentException, ClassNotFoundException, SQLException {
// TODO Auto-generated method stub
Document document = new Document(PageSize.A4.rotate());
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("C:\\columns.pdf"));
document.open();
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test3", "root", "root");
Statement st=con.createStatement();
ResultSet rs=st.executeQuery("select * from exam2");
int size=0;
while (rs.next()){
size++;
};
ResultSet rs1=st.executeQuery("select * from exam2");
String[] myStringArray = new String[size];
int i=0;
while (rs1.next()){
myStringArray[i]=rs1.getString("paper");
i++;
}
ColumnText ct = new ColumnText(writer.getDirectContent());
for (String article : myStringArray) {
ct.addElement(createPhrase(article,writer,document));
ct.addElement(Chunk.NEWLINE);
document.add(Chunk.NEWLINE);
}
ct.setAlignment(Element.ALIGN_CENTER);
ct.setExtraParagraphSpace(55);
ct.setLeading(0, 1.2f);
ct.setFollowingIndent(27);
int linesWritten = 0;
int column = 0;
int status = ColumnText.START_COLUMN;
while (ColumnText.hasMoreText(status)) {
ct.setSimpleColumn(
COLUMNS[column][0], COLUMNS[column][1],
COLUMNS[column][2], COLUMNS[column][3]);
ct.setYLine(COLUMNS[column][3]);
status = ct.go();
linesWritten += ct.getLinesWritten();
column = Math.abs(column - 1);
if (column == 0)
document.newPage();
}
ct.addElement(new Phrase("Lines written: " + linesWritten));
ct.go();
document.close();
}
public static Phrase createPhrase(String myString, PdfWriter writer, Document document) throws IOException, DocumentException {
Phrase p = new Phrase();
String myString2=myString+"<html><body><br></br></body></html>";
String k="<br></br>";
XMLWorkerHelper xwh = XMLWorkerHelper.getInstance();
InputStream is = new ByteArrayInputStream(myString.getBytes());
ElementList myList = new ElementList();
ElementList myList1 = new ElementList();
xwh.parseXHtml(myList,new StringReader(myString2));
p.addAll(myList);
return p;
}
}
When i use XMLWorkerHelper.getInstance().parseXHtml(writer, document, new StringReader(name1)); i am able to preserve the html formatting such as new line.
The below code helps me retrieve html data from DB and parse it while preserving the formatting.However it prints to the pdf in a single column
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.InputStream;
import java.io.StringReader;
import com.itextpdf.text.Document;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import java.io.ByteArrayInputStream;
import java.sql.*;
public class GeneratePDF {
public static void main(String[] args) {
try {
OutputStream file = new FileOutputStream(new File("C:\\Test.pdf"));
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, file);
document.open();
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test3", "root", "root");
Statement st=con.createStatement();
ResultSet rs=st.executeQuery("select paper from exam2 ");
String name1="";
while (rs.next()){
String name = rs.getString("paper");
//out.println(name);
name1=name;
/*String k="<h1 style='text-align: center;'><strong>Maths Question2 Paper</strong></h1>"+
"<pre><strong>1)What is the sum of 2+2??<br /></strong><strong>a)3<br /></strong><strong>b)5<br /></strong><strong>c)4<br /></strong><strong>d)1</strong></pre>"+
"<pre><strong>2)What is the sum of 5+2??<br /></strong><strong>a)3<br />b)5<br />c)7<br />d)1</strong></pre>"+
"<pre> </pre>";*/
System.out.println(name1);
//InputStream is = new ByteArrayInputStream(name1.getBytes());
XMLWorkerHelper.getInstance().parseXHtml(writer, document, new StringReader(name1));
}
document.close();
file.close();
} catch (Exception e) {
e.printStackTrace();
}}}

You're parsing the HTML to a Document. This means you want iText to organize all content on one page, using one column defined by the page size (in your case A4) and the page margins (in your case 36pt on each side).
If you want to organize the content differently, you should use the parseXHTML() method that takes an ElementHandler as parameter and pass an ElementList object. This list will then contain a List of Element objects that you can feed to a ColumnText object. With the ColumnText class, you can define multiple rectangles on a page, and use the go() method to fill these rectangles with the content from the ElementList.

Related

itext5 - how to remove the empty space above a list in a PdfPCell

I am using iText 5. I am following the example found here:
https://web.archive.org/web/20150816002422/http://itextpdf.com/sandbox/tables/ListInCell
/**
* This example was written by Bruno Lowagie for a prospective customer.
* The code in this sample works with the latest version of iText.
* It doesn't work with versions predating iText 5.
*/
package sandbox.tables;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.List;
import com.itextpdf.text.ListItem;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
public class ListInCell {
public static final String DEST = "results/tables/list_in_cell.pdf";
public static void main(String[] args) throws IOException, DocumentException {
File file = new File(DEST);
file.getParentFile().mkdirs();
new ListInCell().createPdf(DEST);
}
public void createPdf(String dest) throws IOException, DocumentException {
Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream(dest));
document.open();
// This is how not to do it (but it works anyway):
// We create a list:
List list = new List();
list.add(new ListItem("Item 1"));
list.add(new ListItem("Item 2"));
list.add(new ListItem("Item 3"));
// We wrap this list in a phrase:
Phrase phrase = new Phrase();
phrase.add(list);
// We add this phrase to a cell
PdfPCell phraseCell = new PdfPCell();
phraseCell.addElement(phrase);
// We add the cell to a table:
PdfPTable phraseTable = new PdfPTable(2);
phraseTable.setSpacingBefore(5);
phraseTable.addCell("List wrapped in a phrase:");
phraseTable.addCell(phraseCell);
// We wrap the phrase table in another table:
Phrase phraseTableWrapper = new Phrase();
phraseTableWrapper.add(phraseTable);
// We add these nested tables to the document:
document.add(new Paragraph("A list, wrapped in a phrase, wrapped in a cell, wrapped in a table, wrapped in a phrase:"));
document.add(phraseTableWrapper);
// This is how to do it:
// We add the list directly to a cell:
PdfPCell cell = new PdfPCell();
cell.addElement(list);
// We add the cell to the table:
PdfPTable table = new PdfPTable(2);
table.setSpacingBefore(5);
table.addCell("List placed directly into cell");
table.addCell(cell);
// We add the table to the document:
document.add(new Paragraph("A list, wrapped in a cell, wrapped in a table:"));
document.add(table);
// Avoid adding tables to phrase (but it works anyway):
Phrase tableWrapper = new Phrase();
tableWrapper.add(table);document.add(new Paragraph("A list, wrapped in a cell, wrapped in a table, wrapped in a phrase:"));
document.add(tableWrapper);
document.close();
}
}
...and it gives a result similar to the sample PDF found here:
https://web.archive.org/web/20140308004615/http://itextpdf.com/sites/default/files/list_in_cell.pdf
My issue is this: you can see that the text in each of the left cells ("list wrapped in a phrase...") is not lined-up horizontally with the first item of each list ("Item 1"). Specifically, I want to move up the text in the right cell's list. How do I do that?
Set cell.PaddingTop = -3f; to move it up a little bit.

Apache beam get kafka data execute SQL error:Cannot call getSchema when there is no schema

I will input data of multiple tables to kafka, and beam will execute SQL after getting the data, but now there are the following errors:
Exception in thread "main"
java.lang.IllegalStateException: Cannot call getSchema when there is
no schema at
org.apache.beam.sdk.values.PCollection.getSchema(PCollection.java:328)
at
org.apache.beam.sdk.extensions.sql.impl.schema.BeamPCollectionTable.(BeamPCollectionTable.java:34)
at
org.apache.beam.sdk.extensions.sql.SqlTransform.toTableMap(SqlTransform.java:141)
at
org.apache.beam.sdk.extensions.sql.SqlTransform.expand(SqlTransform.java:102)
at
org.apache.beam.sdk.extensions.sql.SqlTransform.expand(SqlTransform.java:82)
at org.apache.beam.sdk.Pipeline.applyInternal(Pipeline.java:539) at
org.apache.beam.sdk.Pipeline.applyTransform(Pipeline.java:473) at
org.apache.beam.sdk.values.PCollectionTuple.apply(PCollectionTuple.java:248)
at BeamSqlTest.main(BeamSqlTest.java:65)
Is there a feasible solution? Please help me!
I think you need to set schema for your input collection PCollection<Row> apply with setRowSchema() or setSchema(). The problem is that your schema is dynamic and it's defined in runtime (not sure if Beam supports this). Could you have static schema and define it before starting processing input data?
Also, since your input source is unbounded, you need to define windows to apply SqlTransform after.
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.beam.repackaged.sql.com.google.common.collect.ImmutableMap;
import org.apache.beam.runners.direct.DirectRunner;
import org.apache.beam.sdk.Pipeline;
import org.apache.beam.sdk.extensions.sql.SqlTransform;
import org.apache.beam.sdk.io.kafka.KafkaIO;
import org.apache.beam.sdk.io.kafka.KafkaRecord;
import org.apache.beam.sdk.options.PipelineOptions;
import org.apache.beam.sdk.options.PipelineOptionsFactory;
import org.apache.beam.sdk.schemas.Schema;
import org.apache.beam.sdk.transforms.DoFn;
import org.apache.beam.sdk.transforms.MapElements;
import org.apache.beam.sdk.transforms.ParDo;
import org.apache.beam.sdk.transforms.SimpleFunction;
import org.apache.beam.sdk.values.*;
import org.apache.kafka.common.serialization.StringDeserializer;
import java.util.ArrayList;
import java.util.List;
class BeamSqlTest {
public static void main(String[] args) {
PipelineOptions options = PipelineOptionsFactory.fromArgs(args).as(PipelineOptions.class);
options.setRunner(DirectRunner.class);
Pipeline p = Pipeline.create(options);
PCollection<KafkaRecord<String, String>> lines = p.apply(KafkaIO.<String, String>read()
.withBootstrapServers("192.168.8.16")
.withTopic("tmp_table.reuslt")
.withKeyDeserializer(StringDeserializer.class)
.withValueDeserializer(StringDeserializer.class)
.withConsumerConfigUpdates(ImmutableMap.of("group.id", "beam_app"))
.withReadCommitted()
.commitOffsetsInFinalize());
PCollection<Row> apply = lines.apply(ParDo.of(new DoFn<KafkaRecord<String, String>,Row>(){
#ProcessElement
public void processElement(ProcessContext c) {
String jsonData = c.element().getKV().getValue(); //data: {id:0001#int,name:test01#string,age:29#int,score:99#int}
if(!"data_increment_heartbeat".equals(jsonData)){ //Filter out heartbeat information
JSONObject jsonObject = JSON.parseObject(jsonData);
Schema.Builder builder = Schema.builder();
//A data pipeline may have data from multiple tables so the Schema is obtained dynamically
//This assumes data from a single table
List<Object> list = new ArrayList<Object>();
for(String s : jsonObject.keySet()) {
String[] dataType = jsonObject.get(s).toString().split("#"); //data#field type
if(dataType[1].equals("int")){
builder.addInt32Field(s);
}else if(dataType[1].equals("string")){
builder.addStringField(s);
}
list.add(dataType[0]);
}
Schema schema = builder.build();
Row row = Row.withSchema(schema).addValues(list).build();
System.out.println(row);
c.output(row);
}
}
}));
PCollection<Row> result = PCollectionTuple.of(new TupleTag<>("USER_TABLE"), apply)
.apply(SqlTransform.query("SELECT COUNT(id) total_count, SUM(score) total_score FROM USER_TABLE GROUP BY id"));
result.apply( "log_result", MapElements.via( new SimpleFunction<Row, Row>() {
#Override
public Row apply(Row input) {
System.out.println("USER_TABLE result: " + input.getValues());
return input;
}
}));`enter code here`
}
}

Getting date and time from a NTPUDPClient fails sometimes

I've been working on this program using NetBeans for 6 months and I've never experienced such an issue. It has began when I added org.apache.commons library (I needed it to get time from a online server) , when I run the program ,sometimes everything goes fine and sometimes it hangs on running state creating a process in the background. Here's the Class with the main method.
package samplefx.ctrl;
import java.io.IOException;
import java.net.InetAddress;
import java.sql.Date;
import java.text.ParseException;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import org.apache.commons.net.ntp.NTPUDPClient;
import org.apache.commons.net.ntp.TimeInfo;
public class Optilight extends Application {
public static EntityManagerFactory emf;
EntityManager em;
#Override
public void start(Stage primaryStage) throws IOException, ParseException {
emf = Persistence.createEntityManagerFactory("SampleFXPU");
String TIME_SERVER = "time-a.nist.gov";
NTPUDPClient timeClient = new NTPUDPClient();
InetAddress inetAddress = InetAddress.getByName(TIME_SERVER);
TimeInfo timeInfo = timeClient.getTime(inetAddress);
long returnTime = timeInfo.getMessage().getTransmitTimeStamp().getTime();
Date time = new Date(returnTime);
Access access = new Access();
String fix = "XC193283R";
String var = access.Y();
Date start = Date.valueOf("2016-08-23");
Date end = Date.valueOf("2016-08-31");
Boolean j = false;
if (start.before(time) && time.before(end)) {
j = true;
}
boolean i = false;
if (fix.equals(var)) {
i = true;
}
if (!j || !i) {
System.exit(0);
}
// load main form in to VBox (Root)
BorderPane mainPane = (BorderPane) FXMLLoader.load(getClass().getResource("/samplefx/view/Login.fxml"));
// add main form into the scene
Scene scene = new Scene(mainPane);
//primaryStage.setTitle("Optilight 2.2.1");
primaryStage.setScene(scene);
primaryStage.initStyle(StageStyle.UNDECORATED);
//primaryStage.setMaximized(true); // make the main form fit to the screen
primaryStage.show();
primaryStage.setOnCloseRequest(e -> {
emf.close();
Platform.exit();
System.exit(0);
});
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
I finally found the answer to this, it's a server timeout issue . I added these two lines :
timeClient.open();
timeClient.setSoTimeout(5000);
after this line :
NTPUDPClient timeClient = new NTPUDPClient();

Not able to store value getting from Transliteration using GWT

I am new to GWT and I want to make a application in which words are transliterate and store in a varible.which can be used for storing values in database.
But when I am trying to store in variable it gives null value when am printing it.
package com.google.gwt.language.sample.hellolanguage.client;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.language.client.transliteration.LanguageCode;
import com.google.gwt.language.client.transliteration.SupportedDestinationLanguages;
import com.google.gwt.language.client.transliteration.control.TransliterationControl;
import com.google.gwt.language.client.transliteration.control.TransliterationControlOptions;
import com.google.gwt.language.client.transliteration.text.Transliteration;
import com.google.gwt.language.client.transliteration.text.TransliterationCallback;
import com.google.gwt.language.client.transliteration.text.TransliterationResult;
import com.google.gwt.user.client.ui.Composite;
public class Trans extends Composite {
ArrayList<String> wordsArray= new ArrayList<String>();
public String sss;
public void recieve(String ss)
{
this.sss=ss;
System.out.println(sss);
}
public String send(){
return sss;
}
public Trans(ArrayList<String> str) {
initTransliterationControls(str);
//Here I want to print
System.out.println(sss);
}
public void initTransliterationControls(ArrayList<String> wordsArray1) {
//ArrayList<String> wordsArray= new ArrayList<String>();
// wordsArray=wordsArray1;
//System.out.println(wordsArray1.size());
// for(int i=0;i<wordsArray1.size();i++)
//{
//wordsArray.add(wordsArray1.get(i).toString());
//}
wordsArray.add(wordsArray1.get(0).toString());
wordsArray.add("Rerrebok");
wordsArray.add("Woodland j_74_Hi-gh Heels Boots");
//System.out.println(wordsArray);
Transliteration.transliterate(wordsArray, LanguageCode.ENGLISH,
LanguageCode.HINDI, new TransliterationCallback() {
#Override
public void onCallback(TransliterationResult result) {
// System.out.println(result.getTransliterations().toString());
List<List<String>> collection= new ArrayList<List<String>>();
collection=result.getTransliterations();
// Here I am storing it on sss but when I am print outside this function it gives Null
sss=collection.get(0).get(0).toString();
}
});
}
}

jersey 2 library response.getEntity not exist what should I use instead

my code
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package beans;
import clients.NewJerseyClient;
import entities.ReservationItem;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.ws.rs.core.GenericType;
import parameters.ReservationParam;
import org.glassfish.jersey.client.ClientResponse;
/**
*
* #author subhi2
*/
#ManagedBean
#SessionScoped
public class PageController implements Serializable {
public String moveToPage2() {
NewJerseyClient client = new NewJerseyClient();
ClientResponse response = client.findInsertedReservationItem(ClientResponse.class, "22", "2010-07-26T11:15:51", "2014-07-26T11:15:51");
GenericType<List<ReservationItem>> genericType = new GenericType<List<ReservationItem>>() {
};
// Returns an ArrayList of Players from the web service
List<ReservationItem> data = new ArrayList<ReservationItem>();
data = (response.getEntity(genericType));
return data.toString();
}
}
the line
data = (response.getEntity(genericType));
cause the error
this code was working with old jersey but now what should I do to solve this error ?
You can change response.getEntity(genericType) by response.readEntity(genericType)
For what you are asking I've replaced this
response.getEntity(String.class);
by this
response.getEntityStream().toString();
But there could be another problems related with Jersey 2, I could get it working by replacing these imports
import jersey.spi.container.servlet.ServletContainer;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
By these
import org.glassfish.jersey.servlet.ServletContainer;
import org.glassfish.jersey.client.ClientResponse;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
and in the code (as I was using Jetty) I had to replace this
servletHolder.setInitParameter("com.sun.jersey.config.property.packages",
"resources");
by this
servletHolder.setInitParameter("jersey.config.server.provider.packages",
"resources");
and this
WebResource webResource = client.resource("http://url_u_want_to_connect");
ClientResponse response = webResource.accept("application/json")
by this
WebTarget webTarget = client.target("http://url_u_want_to_connect");
ClientResponse response = webTarget.request("application/json")
Finally here is a link for "latest" docs (It's about Jersey 2.x, at 2013)
https://jersey.java.net/documentation/latest/user-guide.html