Curb the Belly of the Beast: Drag & Drop ServerRequest-Hell And Icefaces

Icefaces supports drag-and-drop functinality regarding its component-library. For sure its easily to implement with much more issues afterwards. Some things brought me almost to cry. If you have a droplistener on your dropArea, your calling event does probably  not bearing your dragged value.



#{workflowTask.name}

Drop Target 1

As you can see, the dropping zone posseses an appropriated dropListener. The regarding Java-Code seems correct for me as well:

   public void addTaskDestinationToTransition(DropEvent event) {
		if (event.getEventType() == DndEvent.DROPPED) {
            String targetId = event.getTargetClientId();
            if ((targetId != null)) {

               WorkflowTask  workflowTask = (WorkflowTask)((HtmlPanelGroup) event.getComponent()).getDragValue();
              ...
            }
        }
	}

But it doesnt matter what i do, the DragValue seems alway be null. Its a bug in IceFaces 1.7.2SP1. Well, be smart, and add instead a dragListener that makes somethin similary. Simply add a dragListener to the dragged component and change the argument of the java-method to DragEvent.

If its done, you run into another problem that seems much harder for me.The dragged component (if its in a drag-state on push the component away from its current place) reverts its state after a few seconds without doing anything. You just holding down the mouse on the left mouse button and moving it on the page up and down…

How can we curbing this issue? Well, at first you have to grasp mostly every reaching of a dropping zone or even moving of the dragging-component invokes an AJAX-Request. And you know, you move the mouse not in everycase straigh forward to the finish-line but more in “flowing-movements” up and down. This increases excessively Pages-Requests that must be avoided. In most cases you dont have an “localhost-infrastructure” rather than a WAN-Landscape wher people will connecting to youre site from india or australia. Its a pidy about that tcp-packet-exchange!!

Well, for me i have implied that this problems belongs to this AJAX-problematic. So if we can stop sending traffic-jam to Skynet we can probably farily increasing our drag-and-drop behaviour.

Icefaces comes along with “sendmasks” which nothing less then descriptive flags about information-states that have to be sent to the server. For instance, if you want to know when a user starts an dragging-operation, this can be exposed as such a flag. Normaly you dont want bother the server (and your self) with such logentries. The only thing you likely want to know is WHAT you´ve dropped- not WHEN OR WHO. So therefore we using the attribute dragMask in every dragging-component to constraining the send-behaviour:



#{workflowTask.name}

Struggles On Alfrescos LDAP-Synchronisation With Multiple Domain-Controllers

What a hell last two days. What guy doesnt know the case, where its all right set but nothing gets to run on these things? A common developer issue and long-term pain ;-)

My current case descripes LDAP-Synchronisation against more than one Active-Directory, respectivally Domain Controller.

An international customer wants to sync users and groups being stored in active directories in Alfresco as well. So well, what for options do we have to achieve this?

Normally you setup in you project the file ldap-synchronisation.properties as well as the regarding context. But whats about that case when your infrastructure consists of multiple Domain Controllers (every DC got its own Active Directory)? For instance you got the domain mycompany.com, your scape could be as following:

mycompany.com

->  de
->  com
->  jp

You can do this if your scape does posses a worldwide-ranged company but has got more localy activities. The more ADs you have the more sync-efford most be taked and for authentication (which is probably synchronously managed with sync as well) you have to do the same and theb… it got worst. Why? Imagine a user that must be binded against 30 or more Domain Controllers to sucessfully authenticate against ONE AD. Thats realy bad.

Well of course, this approach is an option that could be taked as Alfresco supports this in a more detail character. But its not for real an appropriate solution, you know this!

Microsoft introduced therefoe a globaly managed site-catalogue. One (or more) DCs consists  of an schema and links to all DC´s that exists in the company. Locally managed AD-Data will be synchronized with the GC (but not all: normaly email, givenName as well as sn will be mostly synced as well as the sAMAccountName (Accounts Logon Name).

Its a logicaly conclusion to use GC with Alfresco as well! But if you use port 389 (eg.g. ldap://ldap.mycompany.com:389) you got nothing back if you do an ldap search on using the synchronisation of Alfresco. As descriped earlier the GC managed all ADs being replicated to this DC, the port is a different for quering as well.

The port must be  ldap://ldap.mycompany.com:3268. Nothing else must be changed to retrieve employees that working in principal on different countries against locally managed DCs.

Richfaces vs. IceFaces - Towards The War

Its provocant this title, isn´t it?

Oh thats like a common newspaper (like the SUN or Spiegel) to fetch up more customers on using such headlines.  But hey, my google ranking must rise ;-)

But back to topic: Both Richfaces-Extensions offers more functionality to achieve a better and efficient grade of component-management of relying frontend-logic. Both tries to get rid of additional libraries that must else be used to increase user-expierience.

For instance if we looking through the biggest part of both libraries: extensible AJAX-Support.  Ever developer that has already worked with AJAX, that some things must be considered before business software - B2B as well as B2C - can be extended by this technology.

What should be gettin “AJAXized”? In which grade of detail should be used synchronization of the client side with the backend? Which “exchange-protocol” should be taken between client/server?

Last but not least: Do i even need it? Or should i say this in that form: You Aint gonna need it if you dont know what benefit you expect to get! Just using AJAX to “get on ride” in the current AJAX-Hype is just like to buy stock-shares if the value has been doubled in a few time without any essential informations about the underlying company! Whats the parallism between this comparison?

All gets return to its base-value and the regarding “stimula” when we see what efford we expect to obtain if we looking forward in a long-term manner!

But what if you want to use AJAX to achieve an really and essentially benefit from it? Well you bothering yourself with this struggling things descriped above - until a few months.

IceFaces as well as Richfaces introduces a new way of handling AJAX-functionalitiy within a side. In most cases you dont even know that you “programming in ajax mode” but more in JSF-style. You just using tags just like before with all of that things we have to add: Backing Beans, Managed Beans, Navigation Rules, Components and so on. Alls seems to be the same.

What we have: We´ve got a tree, some input fields with an result page that calculates some things based on these fields and a “next” button.

But hey, looking forward to the upfront of your browser and see what appears in Icefaces: All calls are “AJAXized”. And when i said all, its meant to be all of it. Even though we using MyFaces, if we got a root-tag inherited from Icefaces, all commands are AJAXized. Thats a strange thing.

All Or Nothing Its Just Like To Get On The Share Value With ALL THE MONEY To A Company With No Expecting Future! What a Hell-Ride.

What makes Richfaces? As soon as we open the Browser we dont see any Ajax. Oh lol. Wht means “see”? Do we “see ajax” is just like “do we see the black hole”? Richfaces drives another approach to achieve the !same! functionality like Richfaces on using a more expliciticaly decleration “Ajaxized”-Components. Therefore you can use the Tag-Library commonly called”a4j” that introduces components to “invalidate  areas”on client side and harnessing whole component-suites between client and server-site. For instance, if you have a tree that display a menu-structure you can deceide whether the tree gets fully transfered to client side and builded up or partly transfered on using AJAX. Furthermore its possible to say that all request will sent to the server - a fully page reload. Thats a choice of three ways. HOLD, SELL OR BUY. Thats what we want!

Next impressive thing is that we can decide fine-grained AJAX-calls on every component of the client side just on adding an a4j component that triggers on particular events on particular elements like an inputArea (e.g. onclick). Thus, we can sent the current value of this field to the server and synchronously to this we can say that “when its sent to server, rerender a component X that displays the newly added value”. Thats why i love Richfaces!

The next cool thing is, that we can declare an area in which we want to use AJAX. For instance this is usefull on using a wizard. Therefore the actions will be triggered not through “normaly h:commandButtons” rather on using a4j:commandButtons that just doing the “same” thing.  The Scope of the declared DOM-Area will be rerendered on processing such an action. Its so easy, you wont believe it, dont you?

The next adorable technique is very hot. You know the problems if you want to  use wizards or formulars that enters multiple sites? You have to manage beans state as we have such a wizard managed mostly with a session scoped bean. If you want to reuse the wizard you must reinitialize the session. But this brings some side-effects in the round that we doesnt expect at development time.

Richfaces tries to solve this BIG issue by introducing the tag “keepAlive”. All pages that belongs to a Wizard must have such a tag with an attribute being labeled “beanName” with the appropriated value-managed-bean. This managed bean stores all the values of the wizard. You can now set down the scope to request of this bean as the bean have not such a lifetime like a session. What means this? If you visit a site doesnt containt such a tag the bean will be purged from the “Special-Richfaces-Session” and all informations gets lost. Thats what we want. In combination with an a4j:include we have found a realy good solution to get rid of that badly managed session scoped beans.

And to all of this examples i just have to say: It works just from the beginning.

I prefere until now in every web-project that must handle  some ordinary datatypes and progresses Richfaces to improve agility on development and to enhance the User-Expierience.

Get Flowin Baby!

Currently we planned to integrate a sophisticated workflow-engine into our project. Therfore we started from scratch with a new Blueprint therefore.

If you want to know more about the current  state of implementation, please visit following site directly:

 http://www.logicaldoc.info/wiki/index.php?title=BPM:_Workflowsystem

Liferay and Richfaces: Removing Portlets View-ID Caching-State

My current project at my work primarly concerned with Liferay-/Portletcreation. Therefore we have decided to use Richfaces as standard-rich-user-expierience framework as the way on how we can model UI-Objects as well as the afford on which way we want to transmit data from the client to the server in a more fine-grained decision way is very sophisticated. Well if you want to use a ajax-request to transmit the current state of an UI-Tree to the server, just do that on setting up the appropriated tree-element attribute to “ajax”. Particular elements in the tree can be handled in a more different way by transmitting this data through a full-page reload. You got the choice on every element you´ve been pasted on your UI-Site with respect to Richfaces. Very nice feature!

But thats not my comment this days. Well when i looking back into my last post-dates i should gonna be scary. So long i doesnt write any blog-entry? Oh where are my minds? Back to the ISSUE that got every developer that uses Richfaces as its UI-Library in Liferay (i guess in every portal-server supporting JCR-301) .

Well but theres one particular problem if you have some pages connected with each other in a portlet. For instance, XHTML-Site 1 (following being called dogs-view) referes to XHTML-Site 2 (formaly know dogs-card) through an h:commandLink or somewhat else that dives into a FacesRequest to build up the ComponentTree.

If you have visited the  dogs-card(look up in you mind-index what this means, guy!)  on follwing the commandlink from dogs-view the state will be saved within the current portletsession to restore later if no valid commandRequest (e.g. Commandlink request) have been pasted. This is a requirement can happen if you want to revisit dogs-view site. As you know: Dogs-View Site as well as Dogs-Card exists in the same Portlet! If you call the page where you have dropped in this portlet, you got the last state of the portlet. This could be(like explained above) the site dogs-card if this was the last site you´ve visited. But in some cases this is an inappropriated behaviour as it is whished to get the first - “the default” site of a portlet (or somewhat else).

As ive still introduced the portletbridge, jboss implemented the the JCR-301 as well with respect to its own Portal Server as well other Servers like Liferay. The behaviour within the portletbridge saves the current state of the last view of the portlet within the following request attribute:

PortletBridgeContext bridgeContext = (PortletBridgeContext) renderRequest     .getAttribute(PortletBridgeContext.REQUEST_PARAMETER_NAME);

The  parameter PortletBridgeContext.REQUEST_PARAMETER_NAME returns the current bridgeContext (bc). The bc itself will be builded up on each request time.

The portletContext bears the last visited viewid. You got this value on doing following request:

bridgeContext.getWindowState().getViewId();

Well, if you now want to set back portlets view state, you have several opportunities. I´ve decided to choose the way of a portletfilter which can be compared in a more simalary approach with respect to a ServletFilter.

Each  time a portlet will be executed, the portletfilter will be hooking in on the processing line before the portletServlet even know wether the current request belongs to a RenderRequest or an ActionRequest. Thus we have the possibilty given to change pipelines behaviour. As we have said previously, we dont want to render the last portlet state of the portlet if no new actionrequest will be processed. That can be exposed looking for a particlar attribut being set if a link/button have been pressed: org.jboss.portletbridge.VIEWID

If no such Attribute exists in the current request, we change the viewstate of the portletcontext.

To manage this in a more convenient way, we add a xml-file where we can edit the default-view (but we could read out the default-portlet-view given from portlet.xml).

Heres are complete code-snippets:



	
Portlet1
		/xhtml/DocumentsView.xhtml
	
	
Portlet2
		/xhtml/UploadView.xhtml
	
	
Portlet3
		/xhtml/SearchResultsView.xhtml
	
public class DefaultViewFilter implements RenderFilter {

	private static final String facesExtensionResourceUrl = "/de/dmc/customer/web/faces-ext.xml";

	private static HashMap defaultView;

	private static Set defaultViewKeys;

	/**
	 * Wrapperclass for RenderRequest
	 *
	 *
	 * @author wenzkseb
	 *
	 */
	public static final class FinalRenderRequestWrapper extends
			RenderRequestWrapper {

		private String portletName;

		public FinalRenderRequestWrapper(RenderRequest rr, String portletName) {
			super(rr);
			this.portletName = portletName.substring(1);
		}

		/**
		 * Looking for a valid state where the viewid can be changed
		 *
		 * @param name the parameter to obtain
		 * @param bridgeContext BridgeContext
		 * @return the newly valid viewid or null if no valid status for change
		 *         can be found
		 */
		private String retrieveViewState(String name,
				PortletBridgeContext bridgeContext) {

			/*
			 * 1.
			 */
			if (name.equals(”org.jboss.portletbridge.VIEWID”) == false)
				return null;

			if (super.getParameter(name) != null)
				return null;

			if (bridgeContext == null)
				return null;

			for (String _pn : defaultViewKeys) {
				if (portletName.startsWith(_pn + “_WAR”) == true) {
					return defaultView.get(_pn);
				}
			}

			return null;
		}

		@Override
		public String getParameter(String name) {

			PortletBridgeContext bridgeContext = (PortletBridgeContext) getRequest()
					.getAttribute(PortletBridgeContext.REQUEST_PARAMETER_NAME);
			String direction = null;

			if ((direction = retrieveViewState(name, bridgeContext)) != null) {
				bridgeContext.getWindowState().setViewId(direction);
			}

			return super.getParameter(name);

		}
	}

	public void doFilter(RenderRequest request, RenderResponse response,
			FilterChain chain) throws IOException, PortletException {
		chain.doFilter(new FinalRenderRequestWrapper(request, response
				.getNamespace()), response);
	}

	public void destroy() {
		System.out.println(”*********** destroying ****************”);
	}

	/**
	 * Reads the file faces-ext.xml to retrieve all defaultview-mappings:
	 *
	 * 	
	 *      …
	 *		
	 *
DocumentView
	 *	    	/docview/DocumentTableView.xhtml
	 * 		
	 *      …
	 *  
	 */
	public void init(FilterConfig filterConfig) throws PortletException {
		System.out.println(”*********** initializing ***********”);
		System.out.println(”*********** Building up faces ”
				+ “extension for defaultviews ***********”);

		URL facesExtResource = this.getClass().getResource(
				DefaultViewFilter.facesExtensionResourceUrl);

		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder documentBuilder;

		defaultView = new HashMap();

		try {
			documentBuilder = dbf.newDocumentBuilder();
			Document facesDocument = documentBuilder.parse(facesExtResource
					.openConnection().getInputStream());
			NodeList viewList = facesDocument
					.getElementsByTagName(”default-view”);
			for (int idx = 0; idx < viewList.getLength(); idx++) {
				Element currentNode = (Element) viewList.item(idx);

				NodeList _portletName = currentNode
						.getElementsByTagName(”portletname”);
				NodeList _defaultView = currentNode
						.getElementsByTagName(”view-id”);

				if (_portletName.getLength() != 1)
					throw new RuntimeException(”Portletname must be exist”);
				if (_portletName.getLength() != 1)
					throw new RuntimeException(”Defaultview must be exist”);

				_portletName = _portletName.item(0).getChildNodes();
				_defaultView = _defaultView.item(0).getChildNodes();

				if (_portletName.item(0).getNodeValue() == null)
					throw new RuntimeException(”Portletname must no be null”);

				if (_defaultView.item(0).getNodeValue() == null)
					throw new RuntimeException(”Portletname must no be null”);

				String portletName = _portletName.item(0).getNodeValue().trim();
				String defaultView = _defaultView.item(0).getNodeValue().trim();

				System.out.println(”ADD Entry: ” + portletName + “->”
						+ defaultView);

				DefaultViewFilter.defaultView.put(portletName, defaultView);
			}

			defaultViewKeys = defaultView.keySet();

		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

}

DOAG + FuThuer - What Berlin Bears To Us

Yes, i have not forgotten the Berlin-visit 2 months ago (was that visit realy already 2 months ago? where is just the time …).

Many informations i can not present right here due to secrecy that still remains the next time. But in fact, DOAG will be using FuThuers software to built up  a newly educational-portal for doag-specialists, students, oracle-fanboys and - SURELY - companies that needs new staff/personell for its projects as well!

The release/approve of the portal is planned for the next months -May/Juny.

First Try: Solarworlds Online-Released Annual Report

Last weeks was fairly irksome regarding my work until now. Last week we´d released the Online-Version of Solarworlds´s Annual Report which can be found by taking this url: http://2008.kb.solarworld.de/de

Im proud about the team where i was involved a couple of weeks, too. All the stresses and overnight working-doing doesnt stop us in the past. Even far from it we have reached out the result we all had expected in the past.

Now we´ve got more  time… for doing OTHER things like this here - writing to peoples by hearing Opeth in the background.

AlfrescoRuntimeException: Registry root not present

Oh what a day,

after migrating customers alfresco version 1.4 up to 2.2.1 all seems okay(migration has already been made by Lothar,  thanks to that alfresco-geek :)) during merging all customized features at this single point of time. After all, i´ve done a new test-approach assuring that migration works fine from 1.4 to 2.2.1.

But now, for my suprise, alfresco refused startup on telling me that somthing gonna be realy wrong:

...
 at org.apache.catalina.core.StandardService.start(StandardService.java:448)
 at org.apache.catalina.core.StandardServer.start(StandardServer.java:700)
 at org.apache.catalina.startup.Catalina.start(Catalina.java:552)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:295)
 at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:433)

Caused by: org.alfresco.error.AlfrescoRuntimeException: Registry root not present:

   Store: system://system
   Path:  /sys:system-registry

 at org.alfresco.repo.admin.registry.RegistryServiceImpl.getRegistryRootNodeRef(RegistryServiceImpl.java:137)
 at org.alfresco.repo.admin.registry.RegistryServiceImpl.getPath(RegistryServiceImpl.java:184)
 at org.alfresco.repo.admin.registry.RegistryServiceImpl.getChildElements(RegistryServiceImpl.java:326)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...

Realy, i was confused about that error. I really thought at this moment that some data got be missed during schema patch from 1.4 up to 2.2.1.
As alfresco will drop exceptions that could sometimes be missunderstood by developers, we should asking ourself, what for changes have we made between two tries of migrations where the first of them works fine.

The approach was fairly the same, but one thing in alfresco will be changed during first starton migration: Licensing

After the first migration the licence file, being at all times stored on the same place: alfresco/extension/license/*.lic - will be suffixed automatically on appending *.installed upon the filename. This tells alfresco that no new registration of a license must be made.

But here comes the glue: If this license is already being suffixed (grml yet forgotten? *.lic into *.lic.installed)  and an update will be made, the exception above will be your accompanion.

How to solve? Well that is the easy thing of that part on simply renaming this file in a *.lic file.

In other words: We make a rollback for Database-Junkies.

LogicalDOC on connecting Company Wide Information: Upcoming LDAP-Plugin Release

LogicalDOC becoming more maturity regarding companies with a centralised approach of storing business relevant informations. Centralised storages will be normaly associated with use of Directory Servers like Microsoft Active Directory or OpenLDAP. Particular informations, especially user informations, must be accessable through various programs where an authentication is an requirement. Foremost an centralised solution - an Document Management System - that manages important, even confidential, documents it is normaly that a employee getting access to this system on using its logon-informations being stored in the directory server.

Its a pleasure for me to say, that the newly created LDAP-Plugin developed for LogicalDOC getting more a stable status. So its not far away from revealing which is planned to be released with the next version of LogicalDOC 4.5.

What are the features of this plugin?

- automatic synchronising of users and groups in different kind of company locations (for technicans: multiple DNs where users/groups can be stored)

- users will be automatically assigned to the regarding groups being assigned in a directory (e.g. Active Directory)

- Simple- as well as DIGEST-MD5 Authentication available

- ad-hoc synchronisation of a new user: if a user is newly created and the automatic synchronising has not been started until first login

easy configuration of the LDAP/Configuration as predefined configurations for differend kinds of directories exist.

Currently tested directories are: Active Directory Server, OpenLDAP, Apache Directory

(Internet-driven)HTML to PDF with Java

Ah most converters seems to make no sense for me as they producing nothing useable or are overloaded.

I just wanna try to convert a HTML Page into a PDF. Searching through internet bored me down as no concret easy solution(for free) exist. Or im blind, so i can not see this ;-)

First try to achieve “my” easy workaround for this matter:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.net.URL;
import java.util.UUID;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.xerces.parsers.DOMParser;
import org.cyberneko.html.HTMLConfiguration;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xhtmlrenderer.pdf.ITextRenderer;
import org.xml.sax.InputSource;

import com.lowagie.text.DocumentException;

public class Html2Pdf {

	public static String source = "http://www.wikipedia.org";

	public static InputSource getRemoteResource(){

		try {
			//Internet
			return new InputSource(new URL(source).openConnection().getInputStream());
			//FileOperation:
			//return new InputSource(new FileInputStream(source));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public static void prepareImageTags(Document document){
		NodeList nodes = document.getElementsByTagName("img");
        for(int i = 0; i < nodes.getLength(); i++){
        	NamedNodeMap attributes = nodes.item(i).getAttributes();
        	Node srcNode = attributes.getNamedItem("src");
        	String nodeValue = srcNode.getNodeValue();

        	if(nodeValue.startsWith("http")){}
        	else if(nodeValue.startsWith(source) != true){
        		if(nodeValue.startsWith("/") != true)
        			srcNode.setNodeValue(nodeValue + "/");

        		srcNode.setNodeValue(source + srcNode.getNodeValue());
        	}
        }
	}

    public static void main(String[] args)
            throws IOException, DocumentException, Exception {

        String outputFile = "output.pdf";
        OutputStream os = new FileOutputStream(outputFile);

        DOMParser parser = new DOMParser(new HTMLConfiguration());
        parser.setProperty("http://cyberneko.org/html/properties/names/elems", "lower");
        parser.setFeature("http://cyberneko.org/html/features/augmentations", true);

        parser.parse( getRemoteResource() );
        Document doc = parser.getDocument();
        prepareImageTags(doc);

        Document document = parser.getDocument();

        StringWriter stringWriter = new StringWriter();
        StreamResult streamResult = new StreamResult(stringWriter);
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer();

        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
        //we need this strictly as jtidy requires this
        transformer.setOutputProperty(OutputKeys.METHOD, "xml");

        //for some encoding issues, we need to set explictly the preferred output encoding
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        //should be omitted the 
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, “yes”);
        transformer.transform(new DOMSource(document.getDocumentElement()), streamResult);

        //Creating a tempfile and deleting it

        File tempFile = File.createTempFile(”pre_”+UUID.randomUUID().toString()+”_”, “.html”);
        //tempFile.deleteOnExit();
        OutputStreamWriter  fw = new OutputStreamWriter(new FileOutputStream (tempFile), “UTF-8″);
        fw.write(stringWriter.toString());
        fw.close();

        ITextRenderer renderer = new ITextRenderer();

        renderer.setDocument(tempFile);

        renderer.layout();
        renderer.createPDF(os);
        os.close();
    }
}
« go backkeep looking »