Posts in Category "Uncategorized"

URI to reference an XDP in the LC Repository from LC Production Print

There are a few ways of accessing an XDP in the LiveCycle Repository.

One of them is to specify a URI at project design time, in which case the URI will look like this:

LC://servername:8080/Applications/AppName/1.0/hierarchy/yourfile.xdp

However, if you want to specify the URL at run time, you would need to populate a variable.
The face of thge URL changes to:

$varname = “repository:///Applications/AppName/1.0/hierarchy/yourfile.xdp”

The server name and port remain specified in the Select Template dialog, under Runtime Repository.

Some Central instances do not start on Windows 2008

With Central on Windows 2008, if you have multiple instances installed and start Central, some instances will fail to start quoting “open of table (….\JFXXX.TMP) failed”

The Central service in the Windows Services is started, but only some of the instances are running. No specific instance consistently starts or fails, it is random.

This is due to Windows TMP file creation APIs, which changed slightly in Windows 2008. For this reason, any version prior to Central 5.7 is likely to be affected on Windows 2008 (32 and 64 bit) when multiple instances are present.

A patch for Central 5.7 can be obtained from Adobe’s Enterprise Support – you can find their contact details from your Support Agreement.

Internet Explorer crashes when using the Reader or Acrobat plug-in

Sometimes Internet Explorer (32-bit) will crash when using the Reader or Acrobat plug-in to display a PDF in a browser window.

The reason is that some third-party PDF creators use Acrobat’s DLLs, but rather than keep them in their own folders, copy them to system32/ which causes Acrobat to open defunct DLLs – and fall over as a consequence.

To resolve the issue, do the following:

Open C:\Windows\system32

Move the following files somewhere else (for example, create a folder C:\bad_dlls):

ace.dll
AGM.dll
BIB.dll
BIBUtils.dll
JP2KLib.dll
cooltyp.dll

Of course, this means that whatever application installed those DLLs in system32 will stop working.
Identify it, and contact the software’s publisher to check if they have a solution.

If you’re feeling adventurous: You could tentatively open the Acrobat/Reader folder under Program Files\Adobe\Acrobat\Acrobat 9.0\ , and COPY the corresponding DLLs to system32 – but that is of the “dirty hack” class and would be generally disadvisable. The third party PDF application would not necessarily be able to use these DLLs anyway.

Writing formatted text to a Text Field in LC Designer XFA forms

Text fields in XFA forms have a limited support for XHTML markup, allowing rich text text fields in a fillable form.

You can populate these fields using JavaScript, but it requires a bit more trickery than a simple call to field.rawValue

Here’s a script that sets the value of a text field to contain styled text – so long as the text field has its property set to Rich Text

// This is the envelope that the HTML-formatted data needs to be placed in
// remember to escape quote marks

var envel = ‘<?xml version=”1.0″ encoding=”UTF-8″?><exData contentType=”text/html” xmlns=”http://www.xfa.org/schema/xfa-template/2.8/”><body xmlns=”http://www.w3.org/1999/xhtml” xmlns:xfa=”http://www.xfa.org/schema/xfa-data/1.0/” xfa:APIVersion=”Acroform:2.7.0.0″ xfa:spec=”2.1″><p style=”margin-top:0pt;margin-bottom:0pt;font-family:\’Myriad Pro\’;font-size:10pt;text-decoration:none”>PLACEHOLDER</p></body></exData>’;

// This is the HTML-formatted data
var jsdata = ‘<b>Hello</b> <i>Stylish</i> <u>World</u>’;

// put the HTML data in the envelope
jsdata = envel.replace(/PLACEHOLDER/g,jsdata);

// Load the XHTML into the field
// the …, 1, 1 arguments are required for exData to understand the content it seems

form1.sub1.TextField1.value.exData.loadXML(jsdata, 1, 1);

To extract the HTML afterwards, you will need to use “saveXML”. To get just the resulting plain text, you can access via rawValue as normal.

And as AnchorMan says: “Stay Stylish San Diego!” :-)

What’s this PDF ?

[This is not an official Adobe publication. This article may contain errors or omissions, and is subject to change without warning.]

While troubleshooting PDF-related problems, a number of tests come back again and again, and I intend with this article to give a brief overview of basic techniques and considerations on troubleshooting PDF problems.

Note that Reader is the free PDF reading software by Adobe. Acrobat has many more functions including PDF creation, manipulation, analysis, peer-reviewing, tracking, securing…. the list goes on.

Also note that sections referring to browser environments apply to Windows only, as browser plug-ins for Acrobat and Reader are not issued by Adobe for non-Windows operating systems (excpetion: on Mac OS X, browser integration exists only for Safari, but not other browsers)

1) Who’s Driving ?

When in a web browser in Windows, to check what plug-in is rendering the file, you can simply click somewhere in the PDF, and then use the key combo [Ctrl K]

If it is Reader or Acrobat, it will bring up a Reader or Acrobat dialog box.
If it is Acrobat, one of the sets of preferences will be “Convert to PDF”
If you’re in Reader, the PDF conversion preference set will be absent.

Otherwise, anything could happen – within the scope of the PDF reading application. If nothing happens, or a dialog for non-Adobe software appears, then you’re not displaying in Reader or Acrobat.

2) What Are My Rights ?

Through Acrobat, and some other Adobe software, it is possible to restrict how a user uses a PDF: whether they can print, save copies, modify, fill-in forms etc.

To determine this, right-click on a page in the PDF, and select “Document Properties” (available both in Acrobat and Reader)

The Security tab will show you what you are allowed to do with the PDF – whether you can print; add or remove pages, and a few more restrictions.

The Description tab will show you some useful information, of which the “PDF Producer”. Typical Adobe PDF producers are Acrobat, LiveCycle Designer, InDesign, PhotoShop, PDF Maker, PDF Library, Distiller and Adobe Central Output Server Print Agent 5.x.

If your PDF was not created with an Adobe product (in which case, it is not an “Adobe PDF”), and you are having PDF-related problems, then Adobe’s technical support may only be able to provide limited assistance (see http://kb2.adobe.com/cps/328/328140.html ). This also applies when you modify a PDF with a non-Adobe product; this will sometimes leave the PDF producer intact, depending on the software you use.

To test whether an issue occurs with a real Adobe PDF, and you have Acrobat (not Reader) installed, you can try printing the PDF to the “Adobe PDF” printer (available from the “Print…” dialog). This is commonly known as “re-frying” a PDF. This will create a static PDF, whose producer will then be “Adobe Distiller”. You can only do this if you have printing rights on the PDF. Use this new PDF to try to replicate the issue.

3) What Type of Form is my PDF ?

There are two main types of PDF forms that Adobe software produces: forms created directly in Acrobat (not Reader) through the menu item [Forms: Add or Edit Fields]; and those created in LiveCycle Designer (formerly “Adobe Designer”).

The first, created by Acrobat, are known as “AcroForms”. They have static (don’t move) form fields layered on top of static (non-changing) PDF pages.

The other, created by LiveCycle Designer, are called “Dynamic XFA Forms”, or “XFA’s”, whose structure are part encoded in XML, and partly in a native binary format. These have fields that are objects within the rendered PDF, as are nearly all other elements on the pages (with some exceptions, not discussed here). XFA forms can have items that repeat depending on the data entered, have areas of text that change depending on what data is in the form, etc, etc.

This is not to be confused with embedded Flash, which may also be used as a form, and constitutes neither an AcroForm or XFA Form. That would then be a PDF with “embedded content”. You can check this by right-clicking in the form: if you get the contextual menu for FlashPlayer, then you’re in an embedded content PDF.

In Reader, there is no sure-fire way of determining whether you have a dynamic XFA form. Even if the PDF Producer is LiveCycle Designer, you may have a static form that Designer produced.

4) Does My PDF Have a Problem ?

As far as software is concerned, there is only one thing that is certain: either data is badly formatted, or we hope it is well formatted.

There is a functionality in Acrobat (not Reader) that allows you to analyse a PDF, called “Preflight”, available through [menu Advanced: Preflight]

Preflight will analyse the current PDF for any defects, and if you choose, attempt to repair the issues.

A good rule of thumb is: if Preflight says there’s a problem, there’s definitely a problem. If Preflight reports no problems however, there’s no guarantee: it just means Preflight hasn’t been able to detect any problems. If you see a spider, there’s a spider. If you don’t see a spider, maybe there isn’t one – but maybe there’s one behind you.

So if Preflight reports issues with your PDF, and you have problems with that PDF, then it will be considered that the PDF is not compatible with Adobe software. Re-fry the PDF, and try again.

Installing Central on later OS’s

A frequent problem that occurs when installling Adobe Central Output Server is that sometimes a valid serial number is declined at install time. This most frequently happens when installing Central 5.5 on WIndows 2003.

Central 5.5 pre-dates the Windows 2003 operating system, which is not in the installer’s list of accepted OS’s.

To install correctly, you will need to copy the installer to a location on the local drive.

-Inside the installer directory, there is a setup.exe – right-click on this file and select the Compatibility tab

-Select Compatibility Mode for Windows 2000

-Repeat these steps also for the setup.exe in the Software\ directory

This will allow the correct recognition of Windows 20003

You do not need to repeat this for the installed binaries, these will accept the platform without any problems.

What is the maximum number of tabs Reader can have in a browser?

Answer-in-theory: as many as you want

Answer-in-practise: as many as the machine can handle

Full answer:

In Windows, in Firefox, IE7 and IE8, you can opt to view PDFs linked from web pages in your browser. If you start opening a large number of these however, you’ll find that your browser will have a tendancy to complain…

This is due to depletion of desktop heap space. For every tab with a Reader (or Acrobat) plugin, a new Rdr/Acro process is launched, and it uses some heap space resources. So whilst your overall memory (RAM) is not running out, you’ll still find Firefox complaining at you with a dialog saying you have reached the maximum number of documents you can open.

On IE7/IE8 however, you may not see this. IE will merrily open as many PDFs as you tell it to, until it chokes, croaks and crashes. This has been recognized as an IE limitation – Rdr/Acro does not get a chance to display the dialog that prevents you from opening that one-too-many documents.

You can however do the following to prevent the crash (the usual CAVEATS concerning editing the Registry apply):

http://support.microsoft.com/kb/126962/en-us

To correct this problem, increase the size of the desktop heap: Run Registry Editor (Regedt32.exe).
From the HKEY_LOCAL_MACHINE subtree, go to the following key: \System\CurrentControlSet\Control\Session Manager\SubSystems
Select the Windows value.
From the Edit menu, choose String.
Increase the SharedSection parameter.

For Windows NT:
SharedSection specifies the system and desktop heaps using the following format:
SharedSection=xxxx,yyyy
Add “,256″ or “,512″ after the yyyy number.

For Windows 2000, Windows XP, and Windows Server 2003:
SharedSection uses the following format to specify the system and desktop heaps:
SharedSection=xxxx,yyyy,zzz
Increase the zzz number to “256″ or “512.”

With that you should start seeing the dialog pop up when you open too many PDFs.

Of course, you should also question why you are opening so many PDFs at the same time in the first place. It’s just inherently not safe.

Problems running XmlImport from command line in Nix systems

Sometimes you may want to run xmlimport in a Nix system from the command line. If you try this, xmlimport will probably blurt back at you:

~/adobe/central/bin/xmlimport: can’t find resource file jftools.cat!

Even though xmlimport works fine in standard use of Central

The reason is that in your shell, you probably don’t have the proper environment variables set.

See this public document, that seems to be hidden from the web at the time of writing:
http://www.adobe.com/support/products/enterprise/knowledgecenter/c4814.pdf

It refers you to the XmlImport.pdf documentation for UNIX, which lists the environment variables that need to be set for use of xmlimport

The above error can be corrected by setting the NLSPATH variable to

NLSPATH=/home/username/adobe/central/bin/%N:$NLSPATH

And hey presto! now you can use xmlimport from the command line and from your scripts :-)

Cannot deploy LCA on LC ES2

There’s an issue with the string substitution, inside the deployment or compilation code for LC ES2 ; it’s not an obvious one to find either, as the symptoms don’t seem to point to anything at first.

When deploying LCA on LiveCycle ES2, you get an error in the Admin UI

“An error has occurred durring import or deploy. Please see error log for details.”

In the log, there are the following errors

/==
ERROR [org.jboss.ejb.plugins.LogInterceptor] RuntimeException in method: public abstract java.lang.Object com.adobe.idp.dsc.transaction.impl.ejb.adapter.EjbTransactionCMTAdapterLocal.doRequiresNew(com.adobe.idp.dsc.transaction.TransactionDefinition,com.adobe.idp.dsc.transaction.TransactionCallback) throws com.adobe.idp.dsc.DSCException:
java.lang.NullPointerException
==/

As an example, if there is component inside the LCA which is called “My”, the compilation of the LCA will generate a file called “MyService.component” which is located at full-path as below.

During the calculation of the location of the corresponding jar file associated with this component, an incorrect string substitution is used, replacing any occurrence of the explicit string “component” with the new string “compjar”

Component path                "My/1.0/components/MyService.component"
Calculated path               "My/1.0/compjars/MyService.compjar"

The solution then would be, in Workbench ES2, to rename any part of the path to something other than the string “component”. The result would then be, for example:

Component path                "My/1.0/parts/MyService.component"
Calculated path               "My/1.0/parts/MyService.compjar"

Checking the validity of your JMD

One of the things I need to do on a regular basis is check the JMD of an installation, when things don’t seem to be running as they should. More often than not, someone edited the JMD by hand, missed a quote mark – causing havoc with the table alignments.

At other times I just want to be able to read the JMD so that I know what steps are being taken, without having to load/reload various JMDs. And trust me, reading a raw JMD is not fun…

So I came up with the following python script. I’ll be putting it on my personal website at some point, so you can use it there too. In the mean time, have a go at this, if you have a Python CGI server… TableJMD 0.2a


The following highlighting is a backup taken from the corresponging pygments.org post – in case it gets deleted from pygments.org one day…

#! /Program Files/Python25/python

import re,sys,cgi

helpnote = """Table JMD 1.1
(C) 2009 Tai Kedzierski
http://blogs.adobe.com/an_tai/

This tool reads a JMD and writes HTML to STDOUT representing the JMD in a table, as it would be parsed by Central's JfServer.
It also highlights substitution variables not surrounded by double quote marks.

This can either be used from the command line, or as a CGI script on a web site.

From the command line, type:

python tablejmd.py PATH

where PATH is the path to the JMD file
"""

class JMDInvalidLine(Exception):

	def __init__(self,message):
		Exception.__init__(self,message)# = "The line was invalid"

# don't fail silently!
sys.stderr = sys.stdout

def readjmdfile(filename):

	readjmd( open(filename,'rU') )

def readjmd(fileh):

	jmdline = '.'
	
	job_t = dict()
	task_t = dict()

	print_t = dict()
	memory_t = dict()
	
	while jmdline:

		line = fileh.readline()
		if line == '': # EOF

			break
		if re.match(r'(^#)|(^\s*$)',line): # comment or empty line

			continue
		jmdline = jmdsplit(line)
		
		if jmdline == None:

			print "<p>Error parsing line: %s</p>" % (line,)
			continue

		
		if jmdline[0] == '!f':
			if job_t.has_key(jmdline[1] ):

				job_t[jmdline[1] ].append(jmdline)
			else:

				job_t[jmdline[1] ] = [jmdline]
		elif jmdline[0] == '!x':

			if task_t.has_key(jmdline[1] ):
				task_t[jmdline[1] ].append(jmdline)

			else:
				task_t[jmdline[1] ] = [jmdline]

		elif jmdline[0] == '!p':
			if print_t.has_key(jmdline[1] ):

				print_t[jmdline[1] ].append(jmdline)
			else:

				print_t[jmdline[1] ] = [jmdline]
		elif jmdline[0] == '!m':

			if memory_t.has_key(jmdline[1] ):
				memory_t[jmdline[1] ].append(jmdline)

			else:
				memory_t[jmdline[1] ] = [jmdline]

	
	print "<h2>Job table ["+str(len(job_t))+" entries]</h2>"

	print "<table><tbody>"
	print r'<th>Job name</th> <th>Printer name</th> <th>Form file</th> <th>Preamble file</th> <th>Macro number</th> <th>Load flag</th> <th>Task id</th> <th>Input file</th> <th>Output file</th> <th>On error</th> <th>Comments</th>'

	dumptablelines(job_t)
	print "</tbody></table>"
	
	print "<h2>Task table ["+str(len(task_t))+" entries]</h2>"

	print '<p><font color="blue">Blue</font>: not surrounded by doubled double-quotes<br /><font color="red">Red</font>: substitution name does not end with "."</p>'

	print "<table><tbody>"
	print r'<th>Task id</th> <th>[This column reserved]</th> <th>Program name</th> <th>Program options</th> <th>Comments</th>'

	dumptablelines(task_t)
	print "</tbody></table>"
	
	print "<h2>Printer table ["+str(len(print_t))+" entries]</h2>"

	print "<table><tbody>"
	print r'<th>Printer name</th> <th>Printer id</th> <th>Physical device</th> <th>Print agent options</th> <th>Priority</th> <th>Comments</th>'

	dumptablelines(print_t)
	print "</tbody></table>"
	
	print "<h2>Managed Memory table ["+str(len(memory_t))+" entries]</h2>"

	print "<table><tbody>"
	print r'<th>Printer id</th> <th>Managed Memory [bytes]</th> <th>Comments</th>'

	dumptablelines(memory_t)
	print "</tbody></table>"

def dumptablelines(table_t):

	keyset = table_t.keys()
	keyset.sort()
	for entryset in keyset:

		for entry in range(len(table_t[entryset])):
			print "<tr>"

			for col in range(1,len(table_t[entryset][entry]) ):

				print "<td>",table_t[entryset][entry][col],"</td>",
			print "</tr>"

def jmdsplit(line):
	'''INPUT: a line of text from the JMD
OUTPUT: the line, tokenized into a list
'''
	if line[0] != '!':# any meaningful line must start with '!'

		return None
	oline = line
	
	if not line[1] in [

		'f', # job
		'x', # task
		'p', # printer

		'm']: # shared memory
		raise JMDInvalidLine(line)
	
	jmdline = []

	
	try:
		while line:
			token, line = readfirsttoken(line)

			token = atprocess(token) # identify substitution variables and possible errors
			jmdline.append(token)

	except JMDInvalidLine,msg:
		print msg,':',oline

	
	return jmdline

def atprocess(token):
	pat = re.compile(r'((?<!"")[a-zA-Z-]*@[a-zA-Z]+\.?|@[a-zA-Z]+\.(?!""))')

	# NO r'((?<!"")[a-zA-Z-]*@[a-zA-Z]+\.?|@[a-zA-Z]+\.?(?!""))'
	# OK r'((?<!"")[a-zA-Z-]*@[a-zA-Z]+\.?|@[a-zA-Z]+\.(?!""))'
	pat2 = re.compile(r'(@[a-zA-Z]+)(?=[^\.a-zA-Z#])')

	
	if not type(token) == str:
		print type(token)

	
	token = pat.sub(r'<font color="blue">\1</font>',token)

	token = pat2.sub(r'<font color="red">\1</font>',token)

	
	return token
	

def readfirsttoken(line):
	line = re.match(r"\s*(.*)",line).group(1) # remove leading whitespace

	
	if line == '':
		return ('','')
	
	pos = 0

	text = ''
	inquote = False
	inarg = True

	while inarg and pos < len(line):
		if line[pos] == ' ' and not inquote:

			inarg = False
		elif line[pos] == '"' and not inquote:

			inquote = True
			text += line[pos]

		elif line[pos] == '"' and inquote:
			if len(line) == pos+1:

				inarg = False
				inquote = False
			elif line[pos+1] == '"':

				text += '"'
				pos += 1
			else:

				inquote = False
				inarg = False
			text += line[pos]

		else:
			text += line[pos]
		pos += 1

	if inquote:
		raise JMDInvalidLine("Unclosed quote")
	
	return (text,line[len(text):])

# RUNTIME ================================================

def printJMD(thefile):
	print """<html><head><style type="text/css">

body {font-size:9pt}
td, th {
	border-left:2px solid #000000;
	padding: 3px;
	margin: 2px;
	font-size:9pt;
	background-color:#ffffcc;

}

th {
	background-color: #ccffcc;
}
</style>
<title>Table JMD - Done</title>
</head><body>

<h1>Table JMD</h1>"""
	print "<!-- ",helpnote," -->"
	readjmd(thefile)

	print "</body></html>"

def printform():
	print """<html>

<head><title>Table JMD</title></head>
<body>
<h1>Table JMD</h1>

<form action="tablejmd.py" method="POST" name="logprint" enctype="multipart/form-data">

<p>Check your JMD Tables.</p>
File: <input type="file" name="jmdfile" /><br />
<input type="submit" />

</form>
</body></html>
"""

# RUNTIME

#print "Content-Type: text/plain"
#print

fs = cgi.FieldStorage()

if fs.has_key('jmdfile'):
	print "Content-Type: text/html"
	print

	
	printJMD(fs['jmdfile'].file)
	
	#print '<p><b>Displaying JMD table for '+fs['jmdfile'].filename+'</b></p>'

	
elif len(sys.argv) > 2 and sys.argv[1] == '-f':

	printJMD(sys.argv[2])
elif len(sys.argv) > 1:

	if re.match(r'-h|/h|--help|/\?|-\?',sys.argv[1]):

		print helpnote
else:
	print "Content-Type: text/html"
	print
	printform()