Anchor and Chunk not working in iText 2.1.7 - hyperlink

All,
Good morning.
I was trying to create Links from one part of PDF document to other part using iText.
Version of iText I use is 2.1.7
I tried using both Anchors and Chunks and neither are working. Basically the link does not become Clickable at all.
Here is the Destination code with Anchor and Chunk:
Anchor anchor = new Anchor("Reach here");
anchor.setName("DestinationID");
pdfDocument.add(anchor);
Chunk chunk = new Chunk("Reach here");
chunk.setLocalDestination("DestinationID");
pdfDocument.add(chunk);
Here is the Link code with Anchor and Chunk:
Anchor anchor = new Anchor("Click Here", PDFConstants.HELVETICA_8_BOLD_UNDERLINE);
anchor.setReference("#DestinationID");
cell.add(anchor);
Chunk chunk = new Chunk("Click Here", PDFConstants.HELVETICA_8_BOLD_UNDERLINE);
chunk.setLocalGoto("DestinationID");
cell.add(chunk);
// cell gets added to a Table later
Appreciate if someone could point what I was doing wrong.
thank you,
Raghavan

You have to take in account the Bruno Lowagie comments and upgrade your version because iText 2.1.7 is an old version an doesn't complain with new PDFReference specifications.
Anywise I don't see anything wrong in your code snippet, may be the problem is in the rest of your code which you're not showing up. I did a simple test with Chunk with a 2.1.7 version an it worked, I give you my sample if you want to check if there is something that could help you:
import java.awt.Color;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import com.lowagie.text.Cell;
import com.lowagie.text.Chunk;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.FontFactory;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Table;
import com.lowagie.text.pdf.PdfWriter;
public class PDFChunkTest {
public static void main(String[] args) throws FileNotFoundException, IOException, DocumentException {
Document doc = new Document();
PdfWriter writer = PdfWriter.getInstance(doc,new FileOutputStream("C:/temp/pdf.pdf"));
doc.open();
Chunk chunk = new Chunk("click here", FontFactory.getFont(FontFactory.HELVETICA, 8, Font.BOLD, new Color(0, 0, 255)));
chunk.setLocalGoto("test");
Table tab = new Table(1, 2);
Cell cell = new Cell();
cell.add(chunk);
tab.addCell(cell);
doc.add(tab);
Paragraph p2 = new Paragraph("Lorem ipsum dolor sit amet...");
doc.add(p2);
doc.add(p2);
doc.add(p2);
doc.add(p2);
doc.add(p2);
doc.add(p2);
Chunk chunk2 = new Chunk("local destination", FontFactory.getFont(FontFactory.HELVETICA, 8, Font.BOLD, new Color(0, 0, 0)));
chunk2.setLocalDestination("test");
doc.add(chunk2);
doc.close();
}
}

Related

How do i "just use" Thymeleaf?

i tried to find tutorials online, but i only found them in the context of web applications. in my case what i have is an html template that i want to fill "manually", meaning it should run from a static main method without spring or any other framework. just "plain thymeleaf"
i have for example a test html file containing:
<p th:text="#{test.message}">This is a report</p>
how does the java code look like that simply fills this variable? i couldn't find a minimal running code example.
The following is a standalone Thymeleaf demo (no web application needed; no Spring used):
Assumptions:
I have a messages file called test.properties containing the following:
test.message=This is a message to you.
I have a related HTML template called test.html:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<p th:text="#{test.message}">This is a report</p>
<p th:text="${note}">This is a note</p>
</html>
In the above template, I added Thymeleaf variable expression (${note}), as well as the message expression - just to make the demo more complete. You may not even need that.
You need to make sure that the HTML template and the properties file are in the same location, because I am using the StandardMessageResolver - see below.
I created a standalone Thymeleaf template engine class:
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import org.thymeleaf.context.Context;
import org.thymeleaf.extras.java8time.dialect.Java8TimeDialect;
import org.thymeleaf.messageresolver.IMessageResolver;
import org.thymeleaf.messageresolver.StandardMessageResolver;
import java.util.Map;
public class HtmlTemplateEngine {
private final TemplateEngine templateEngine;
public HtmlTemplateEngine() {
templateEngine = new org.thymeleaf.TemplateEngine();
templateEngine.addDialect(new Java8TimeDialect()); // optional extra
ClassLoaderTemplateResolver templateResolver
= new ClassLoaderTemplateResolver(Thread
.currentThread().getContextClassLoader());
templateResolver.setTemplateMode(TemplateMode.HTML);
templateResolver.setPrefix("/thymeleaf/");
templateResolver.setCacheTTLMs(3600000L); // one hour
templateResolver.setCacheable(true);
templateResolver.setCharacterEncoding("UTF-8");
templateEngine.setTemplateResolver(templateResolver);
IMessageResolver messageResolver = new StandardMessageResolver();
templateEngine.setMessageResolver(messageResolver);
}
// use this if you do not want to pass a Context (see below). It basically does
// the same as the Context-based example, by transferring Map data to a Context:
public String getTemplate(String templateName, Map<String, Object> parameters) {
Context ctx = new Context();
if (parameters != null) {
parameters.forEach((k, v) -> {
ctx.setVariable(k, v);
});
}
return this.templateEngine.process(templateName, ctx).trim();
}
public String getTemplate(String templateName, Context ctx) {
return this.templateEngine.process(templateName, ctx).trim();
}
}
Some of the entries are default values - so they could be removed without affecting anything (for example the StandardMessageResolver will be used by default if you do not provide one).
I chose to use a ClassLoaderTemplateResolver. There are other choices you can make.
I use the above artifacts as follows:
private void processSimpleReport() {
Map<String, Object> model = new HashMap<>();
model.put("note", "my note here");
Context ctx = new Context();
//ctx.setLocale(Locale.US); // optional for i18n
ctx.setVariables(model);
HtmlTemplateEngine engine = new HtmlTemplateEngine();
String s = engine.getTemplate("test.html", ctx);
System.out.println(s);
}
Your question only uses a message - the model variables are just optional extras I added for this demo.
The resulting HTML is:
<!DOCTYPE html>
<html>
<p>This is a message to you.</p>
<p>my note here</p>
</html>

Checking HTML document with REST Assured

I'm trying to use REST Assured to check some properties on an HTML document returned by my server. An SSCCE demonstrating the problem would be as follows:
import static com.jayway.restassured.path.xml.config.XmlPathConfig.xmlPathConfig;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import org.junit.Test;
import com.jayway.restassured.path.xml.XmlPath;
public class HtmlDocumentTest {
#Test
public void titleShouldBeHelloWorld() {
final XmlPath xml = new XmlPath("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\">"
+ "<head><title>Hello world</title></head><body></body></html>")
.using(xmlPathConfig().with().feature("http://apache.org/xml/features/disallow-doctype-decl", false));
assertThat(xml.get("//title[text()]"), is("Hello world"));
}
}
Now, this attempt ends in com.jayway.restassured.path.xml.exception.XmlPathException: Failed to parse the XML document caused by, off all the possible errors, java.net.ConnectException: Connection timed out after some 30 seconds or so!
If I remove the line with the xmlPathConfig().with().feature(...) the test fails immediately due to DOCTYPE is disallowed when the feature "http://apache.org/xml/features/disallow-doctype-decl" set to true..
If I remove the doctype line from the document the parsing succeeds but the test fails on an assertion error, "Expected: is "Hello world" but: was <Hello worldnull>" -- however, that's a different problem, obviously (but feel free to give instructions on that one, too...). And removing the doctype isn't an option for me anyway.
So, question: how do you check properties of an HTML document with a doctype using REST Assured? It says in the documentation that "REST Assured providers predefined parsers for e.g. HTML, XML and JSON.", but I cannot seem to find any examples on how exactly to activate and work with that HTML parser! There's no "HtmlPath" class like there's XmlPath, for example, and that timeout exception is very puzzling...
I checked your code. The thing is that XmlPath of Restassured isn't Xpath, but uses a property access syntax. If you add a body content to your sample HTML you will see that your XPath doesn't do much. The actual name of the query language is GPath. The following example works, note also the use of CompatibilityMode.HTML, which has the right config for you need:
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import com.jayway.restassured.path.xml.XmlPath;
import com.jayway.restassured.path.xml.XmlPath.CompatibilityMode;
public class HtmlDocumentTest {
#Test
public void titleShouldBeHelloWorld() {
XmlPath doc = new XmlPath(
CompatibilityMode.HTML,
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\">"
+ "<head><title>Hello world</title></head>"
+ "<body>some body"
+ "<div class=\"content\">wrapped</div>"
+ "<div class=\"content\">wrapped2</div>"
+ "</body></html>");
String title = doc.getString("html.head.title");
String content = doc.getString("html.body.div.find { it.#class == 'content' }");
String content2 = doc.getString("**.findAll { it.#class == 'content' }[1]");
assertEquals("Hello world", title);
assertEquals("wrapped", content);
assertEquals("wrapped2", content2);
}
}
If you're using the DSL (given/when/then) then XmlPath with CompatibilityMode.HTML is used automatically if the response content-type header contains a html compatible media type (such as text/html). For example if /index.html contains the following html page:
<html>
<title>My page</title>
<body>Something</body>
</html>
then you can validate the title and body like this:
when().
get("/index.html").
then().
statusCode(200).
body("html.title", equalTo("My page"),
"html.body", equalTo("Something"));
Here is sample code with the latest rest assured apis, i.e. io.restassured and not the older jayway.restassured. The explanation for the code is in the code comments.
//Demo for an api which returns a json string inside html. The json string is just an array of objects.
import io.restassured.RestAssured;
import io.restassured.path.json.JsonPath;
import io.restassured.response.Response;
import java.util.List;
import static io.restassured.RestAssured.*;
public void testMyApi() {
Response response =
when().
get("www.myapi.com/data").
then().
extract().
response();
String bodyTxt = response.htmlPath().getString("body");//Get the body element of the html response.
JsonPath jsonObj = new JsonPath(bodyTxt);//helps us to find things in a json string.
List<String> rootItems = jsonObj.getList("$");//get root element of the json part.
System.out.println(rootItems);
}

How to convert a Dart Html client web socket response from Blob to Uint8List?

I’ve implemented my own binary message protocol for simple request/response objects from a Dart client to a Java server. These are encoded in Dart as an Uint8List and on the remote server in Java as a ByteBuffer. The round trip works for the WebSocket in [dart:io] because the websocket.listen stream handler in the Dart client command app is passed data typed as Uint8List.
In [dart:html] the response data in MessageEvent.data received from the websocket.onMessage stream is typed as Blob. I’m not finding a way to convert the Blob to Uint8List. Because the response will often be a large binary array of numbers (double) that will be supplying data to a virtual scrolling context, I want to minimize copying. Could someone please point me in the right direction.
According to this article, you need to use a FileReader to do this.
This example seems to work, the result type is a Uint8List when I tested this in Chrome.
var blob = new Blob(['abc']);
var r = new FileReader();
r.readAsArrayBuffer(blob);
r.onLoadEnd.listen((e) {
var data = r.result;
print(data.runtimeType);
});
Another option is to set WebSocket.binaryType to "arraybuffer". Then MessageEvent.data will return a ByteBuffer which can be turned into a Uint8List. See the example below.
import 'dart:html';
import 'dart:typed_data';
void main() {
var ws = new WebSocket('...')..binaryType = 'arraybuffer';
ws.onMessage.listen((MessageEvent e) {
ByteBuffer buf = e.data;
var data = buf.asUint8List();
// ...
});
}

How to create caption of combobox at the same line?

Vaadin's comboBoxes were designed to show captions and items are line by line (you can see them in here). If I want to see them in a same line , what is the solution ?
Now I am trying to get as below ....
HorizontalLayout hlMain = new HorizontalLayout();
hlMain.addComponent(new Label("Gender:"));
final ComboBox gender = new ComboBox("" , genderList);
hlMain.addComponent(gender);
But I know above code is too ugly , So I am trying to use with CSS . I would like to know has there easy way to get it with Vaadin ? Any suggestions will be great help for me.
If you are willing to dedicate a layout to this, use a FormLayout:
// run with: spring run vaadin.groovy
#Grapes([
#Grab('org.vaadin.spring:spring-boot-vaadin:0.0.5.RELEASE'),
#Grab('com.vaadin:vaadin-server:7.4.4'),
#Grab('com.vaadin:vaadin-client-compiled:7.4.4'),
#Grab('com.vaadin:vaadin-themes:7.4.4'),
])
import org.vaadin.spring.annotation.VaadinUI
import com.vaadin.server.VaadinRequest
import com.vaadin.ui.*
#VaadinUI
class MyUI extends UI {
protected void init(VaadinRequest request) {
setContent(new FormLayout( // XXX
new ComboBox("Gender:").with{ addItem("M"); addItem("F"); it }
))
}
}
Your current code would work, if you would not put the empty caption on the ComboBox (it makes Vaadin think, that there is something to show and render an empty line, break, and then the combobox). Yet FormLayout is the superior solution.
// run with: spring run vaadin.groovy
#Grapes([
#Grab('org.vaadin.spring:spring-boot-vaadin:0.0.5.RELEASE'),
#Grab('com.vaadin:vaadin-server:7.4.4'),
#Grab('com.vaadin:vaadin-client-compiled:7.4.4'),
#Grab('com.vaadin:vaadin-themes:7.4.4'),
])
import org.vaadin.spring.annotation.VaadinUI
import com.vaadin.server.VaadinRequest
import com.vaadin.ui.*
#VaadinUI
class MyUI extends UI {
protected void init(VaadinRequest request) {
setContent(new HorizontalLayout(
new Label("Gender"),
new ComboBox().with{ addItem("M"); addItem("F"); it } // no label!
))
}
}
You can use Vaadin FormLayout component wherever you required to put caption before input fields.
Example:
// A FormLayout used outside the context of a Form
FormLayout fl = new FormLayout();
// Make the FormLayout shrink to its contents
fl.setSizeUndefined();
TextField tf = new TextField("A Field");
fl.addComponent(tf);
// Mark the first field as required
tf.setRequired(true);
tf.setRequiredError("The Field may not be empty.");
TextField tf2 = new TextField("Another Field");
fl.addComponent(tf2);

Reading remote text file with AIR, spaces and links

I have a text file(txt) in my web server. I will read the file contents and show it to user. The problem is that it does not show line separations and spaces the right way. Also i will need to activate possible links. For example if there is http://www.google.com then user can just click on the link and default browser opens it.
So far i have this:
var fileContents:String;
try{
var myLoader:URLLoader = new URLLoader();
myLoader.addEventListener(Event.COMPLETE, onFileLoaded);
myLoader.load(new URLRequest("http://my.website.com/test.txt"));
function onFileLoaded(e:Event):void
{
fileContents = String(e.currentTarget.data);
var alertMessage = fileContents;
I have done this same thing in java, but I am not so familiar with ActionScript.
Java code:
URL url = new URL(getString(R.string.url));
BufferedReader r = new BufferedReader(new InputStreamReader(
url.openStream(), "UTF-8"));
StringBuilder total = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
total.append(line);
total.append(System.getProperty("line.separator"));
}
str = total.toString();
r.close();
return str;
Links in java:
final SpannableString s = new SpannableString(sUrl);
Linkify.addLinks(s, Linkify.WEB_URLS);
You might consider using the Text Layout Framework (TLF) from Adobe. You can import the text as HTML and it will create clickable links for any URL's found in the text. TLF is a bit unwieldy, but very powerful.
private var myTextFlow:TextFlow = TextConverter.importToFlow(sourceText, TextConverter.TEXT_FIELD_HTML_FORMAT);
If you are using Flex 4, can assign the resulting TextFlow object to one of the text components:
<s:RichText textFlow="{myTextFlow}" />
In an Actionscript project, you have to do a little more work to use the TextFlow. TLF uses an MVC approach. The TextFlow serves as the model, you can use a Sprite for the view, and a ContainerController as the controller:
private var container:Sprite = new Sprite();
addChild(container);
private var controller:ContainerController = new ContainerController(container, 800,600);
myTextFlow.flowComposer.addController(controller);
myTextFlow.flowComposer.updateAllControllers();

Resources