tag:blogger.com,1999:blog-101893962024-03-06T02:38:49.883+05:30Experientia docet. By Vineet Reynolds.The chronicles of an engineer.Anonymoushttp://www.blogger.com/profile/13688757724895249188noreply@blogger.comBlogger16125tag:blogger.com,1999:blog-10189396.post-82352284525287344902012-12-01T10:49:00.001+05:302012-12-03T07:13:38.603+05:30Getting the GlassFish 3.1.2 updatetool to work on Ubuntu/Mint 64-bitI wrestled with the GlassFish updatetool monster for a couple of hours, and I decided to spare someone else the trouble of going through this all over again.<br />
<br />
If you're using GlassFish 3.1.2 on a 64-bit OS, you're likely to run into a couple of bugs related to the GlassFish update tool. More likely so, if you've installed GlassFish off the ZIP bundles available at glassfish.java.net - extracting these archives do not install the updatetool utility.<br />
<h2>The JVM crash</h2><br />
I ran into a segfault when running the updatetool from the commandline. Portions of the reported fault are listed below:<br />
<br />
<code><br />
Proxy: Using system proxy settings.<br />
Install image: /opt/glassfish-3.1.2.2/glassfish3<br />
Installing pkg packages.<br />
Downloading 2 packages.<br />
Downloading pkg (511 files, 6,237,937 bytes).<br />
thread 140690402031360 also had an error]<br />
#<br />
# A fatal error has been detected by the Java Runtime Environment:<br />
#<br />
# SIGSEGV (0xb) at pc=0x00007ff50b573920, pid=25590, tid=140690403084032<br />
#<br />
# JRE version: 7.0_09-b05<br />
# Java VM: Java HotSpot(TM) 64-Bit Server VM (23.5-b02 mixed mode linux-amd64 compressed oops)<br />
# Problematic frame:<br />
# C [libdbus-1.so.3+0x26920] dbus_watch_handle+0x1b20<br />
#<br />
# Core dump written. Default location: /opt/glassfish-3.1.2.2/glassfish3/bin/core or core.25590<br />
#<br />
# An error report file with more information is saved as:<br />
# /opt/glassfish-3.1.2.2/glassfish3/bin/hs_err_pid25590.log<br />
</code><br />
<br />
Opening the pid error log showed the actual cause:<br />
<br />
<code><br />
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)<br />
j sun.net.spi.DefaultProxySelector.getSystemProxy(Ljava/lang/String;Ljava/lang/String;)Ljava/net/Proxy;+0<br />
j sun.net.spi.DefaultProxySelector.access$100(Lsun/net/spi/DefaultProxySelector;Ljava/lang/String;Ljava/lang/String;)Ljava/net/Proxy;+3<br />
j sun.net.spi.DefaultProxySelector$2.run()Ljava/net/Proxy;+151<br />
j sun.net.spi.DefaultProxySelector$2.run()Ljava/lang/Object;+1<br />
v ~StubRoutines::call_stub<br />
j java.security.AccessController.doPrivileged(Ljava/security/PrivilegedAction;)Ljava/lang/Object;+0<br />
j sun.net.spi.DefaultProxySelector.select(Ljava/net/URI;)Ljava/util/List;+223<br />
j sun.net.www.protocol.http.HttpURLConnection.plainConnect()V+314<br />
j sun.net.www.protocol.http.HttpURLConnection.connect()V+1<br />
j sun.net.www.protocol.http.HttpURLConnection.getInputStream()Ljava/io/InputStream;+195<br />
j java.net.HttpURLConnection.getResponseCode()I+16<br />
j com.sun.pkg.client.Image.checkRepositoryConnection(Ljava/net/HttpURLConnection;)V+1<br />
j com.sun.pkg.client.DownloadFileTask.download()Ljava/io/File;+73<br />
j com.sun.pkg.client.DownloadFileTask.call()Ljava/io/File;+1<br />
j com.sun.pkg.client.DownloadFileTask.call()Ljava/lang/Object;+1<br />
j java.util.concurrent.FutureTask$Sync.innerRun()V+29<br />
j java.util.concurrent.FutureTask.run()V+4<br />
j java.util.concurrent.ThreadPoolExecutor.runWorker(Ljava/util/concurrent/ThreadPoolExecutor$Worker;)V+46<br />
j java.util.concurrent.ThreadPoolExecutor$Worker.run()V+5<br />
j java.lang.Thread.run()V+11<br />
v ~StubRoutines::call_stub<br />
</code><br />
<br />
This turned out to be <a href="http://java.net/jira/browse/GLASSFISH-18360">GLASSFISH-18360</a>. Applying the workaround listed in that report was sufficient to bypass the problem - you'll merely need to update the updatetool script to set the value of "proxy.use.system" to false. Of course, this works if you're not using a proxy.<br />
<br />
Now, you should be able to install the updatetool utility.<br />
<h2>The 32-bit libraries</h2><br />
That wasn't good enough though. Running updatetool after installation, resulted in this message:<br />
<br />
<code><br />
Locale could not be determined. Attempting to use English locale.<br />
WX import error. Verify the WX widgets are in the PYTHONPATH.<br />
The following can be reported to GlassFish Update Tool 2.3.5 Development Team <dev@updatecenter.java.net>.<br />
<br />
Traceback (innermost last):<br />
File "/opt/glassfish-3.1.2.2/glassfish3/updatetool/vendor-packages/updatetool/common/boot.py", line 283, in init_app_locale<br />
import wx<br />
File "wx/__init__.py", line 45, in ?<br />
File "wx/_core.py", line 4, in ?<br />
ImportError: libjpeg.so.62: cannot open shared object file: No such file or directory<br />
<br />
---------------------------------------------------------------<br />
There was an error running<br />
<br />
/opt/glassfish-3.1.2.2/glassfish3/updatetool/bin/../../pkg/python2.4-minimal/bin/python<br />
</code><br />
<br />
The weird bit about this was that the ia32-libs package required by updatetool was already installed. The problem turned out to be the use of the 64-bit version of libjpeg:<br />
<br />
<pre>$ locate libjpeg.so
/usr/lib/jvm/jdk1.7.0_07/jre/lib/amd64/libjpeg.so
/usr/lib/x86_64-linux-gnu/libjpeg.so.8
/usr/lib/x86_64-linux-gnu/libjpeg.so.8.0.2
</pre><br />
On 64-bit Mint or Ubuntu, <a href="http://java.net/projects/updatecenter/lists/dev/archive/2012-05/message/0">you'll need to explicitly install the i386 version</a>:<br />
<br />
<code>sudo apt-get install libjpeg62:i386</code><br />
<br />
That should do be sufficient:<br />
<br />
<pre>$ locate libjpeg.so
/usr/lib/i386-linux-gnu/libjpeg.so.8
/usr/lib/i386-linux-gnu/libjpeg.so.8.0.2
/usr/lib/jvm/jdk1.7.0_07/jre/lib/amd64/libjpeg.so
/usr/lib/x86_64-linux-gnu/libjpeg.so.8
/usr/lib/x86_64-linux-gnu/libjpeg.so.8.0.2
</pre><br />
Running updatetool now should bring up the GUI.Anonymoushttp://www.blogger.com/profile/13688757724895249188noreply@blogger.com5tag:blogger.com,1999:blog-10189396.post-36916441466847874152012-11-14T22:02:00.000+05:302012-11-26T12:02:41.694+05:30The embedded EJB container in WebLogic Server 12cThe EJB 3.1 specification requires that all containers support embedded usage, with the additional requirement to support the EJB Lite feature set in an embedded container environment.<br />
<br />
WebLogic 12c has had this feature since it's first release in Dec 2011, but apart from some sparse documentation on OTN, there was no material describing it's usage. I could not get it to work in a suitable manner, when I first attempted to write an Arquillian adapter earlier this year. Since then, I've had time to "peek" into it's internals and get it working.<br />
<br />
Before we proceed, I'd like to issue a warning - <i>use this at your own risk. Some of this is not documented in the WebLogic Server documentation at this time, and some use cases are most likely not supported by Oracle.</i> These notes are based on the WLS 12c developer installation pack hosted on OTN.<br />
<br />
<h2>
The embedded EJB container provider</h2>
<h3>
Starting the embedded container</h3>
The WLS embedded EJB container is initialized just like other embeddable containers:<br />
<br />
<pre class="brush:java">EJBContainer container = javax.ejb.embeddable.EJBContainer.createEJBContainer();
</pre>
<br />
At this point, an implementation of the <a href="http://docs.oracle.com/javaee/6/api/javax/ejb/spi/EJBContainerProvider.html">javax.ejb.spi.EJBContainerProvider</a> interface is located and loaded from the classpath. In the case of WLS 12c, the implementation and it's dependent classes can be found in weblogic.jar. It is also possible to use wlclient.jar or wlfullclient.jar instead, but I ended up running into CNFEs that I did not want to pursue; documentation of the required JARs for the embedded container would have helped here.<br />
<br />
Note - copying over weblogic.jar and using it in your project is also bound to result in CNFEs. The weblogic.jar file uses relative paths in it's ClassPath manifest entry, and hence you would be required to replicate the entire file system structure of WL_HOME/modules and WL_HOME/server/lib at a minimum.<br />
<br />
Note about using Surefire - If you're using Surefire to run your tests that depend on the EJBContainer API, you should add weblogic.jar as an<span class="tag"> <span style="font-family: "Courier New",Courier,monospace;">additionalClasspathElement</span> entry in your POM. Of course, you'll need to use an absolute path, but this way, you avoid the problems associated with installing weblogic.jar as a Maven artifact in your repository - you no longer need to figure out how to create a uber weblogic.jar or manage the transitive dependencies of the same.</span><br />
<h3>
Using the embedded container in a test</h3>
The most common use of an embedded container is in running tests. While embedded containers have their disadvantages over their standalone counterparts, developers tend to prefer embedded containers primarily for their startup performance.<br />
<br />
For the sake of demonstrating a test involving an embedded container, consider a SLSB with a no-interface view:<br />
<br />
<pre class="brush:java">package com.acme.ejb;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
@Stateless
@LocalBean
public class Greeter {
public String sayHello(String name) {
return "Hello " + name;
}
}
</pre>
<br />
The following JUnit4 test demonstrates the usage of the embedded container to test the SLSB:<br />
<br />
<pre class="brush:java">package com.acme.test;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.junit.Assert.assertThat;
import javax.ejb.embeddable.EJBContainer;
import javax.enterprise.inject.spi.BeanManager;
import javax.naming.Context;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import com.acme.ejb.Greeter;
public class GreetingTest {
private static Greeter greeter;
private static EJBContainer ejbContainer;
private static Context ctx;
@BeforeClass
public static void setupContainer() throws Exception {
ejbContainer = EJBContainer.createEJBContainer();
ctx = ejbContainer.getContext();
}
@Before
public void setup() throws Exception {
greeter = (Greeter) ctx.lookup("java:global/classes/GreeterBean");
}
@AfterClass
public static void shutdownContainer() throws Exception {
if (ejbContainer != null) {
ejbContainer.close();
}
}
@Test
public void testGreeter() throws Exception {
String message = greeter.sayHello("World");
assertThat(message, equalTo("Hello World"));
}
}
</pre>
<br />
While the @Test method itself completes in the order of milliseconds, the rest of the setup activity involving startup of the embedded container and deployment of the EJB runs into a few seconds (~20 on my workstation). If you are testing components of your application that use the EJB Lite features, this is a possible way to cut down on test execution time. I am of course assuming that you do not run into the typical issues involving embedded container usage.<br />
<br />
I found it a bit surprising when I had to use the <span style="font-family: "Courier New",Courier,monospace;">java:global</span> namespace to lookup the deployed SLSB. Although the container bound the SLSB to several JNDI names, including the <span style="font-family: "Courier New",Courier,monospace;">java:app</span> and <span style="font-family: "Courier New",Courier,monospace;">java:module</span> namespaces, using the other names during lookup failed. This is either a bug, or a feature - WLS allows lookups in these namespaces from within the SLSB but not from the test class.<br />
<br />
<br />
Note - the embedded container of WLS does not truly shutdown when the <span style="font-family: "Courier New",Courier,monospace;">EJBContainer.close()</span> method is invoked. A few user (non-daemon) threads continue to run, and therefore a complete shutdown occurs only when System.exit/Runtime.exit is invoked. Failure to invoke System.exit/Runtime.exit would leave the JVM in a running state. TestRunners usually do not have this problem, but if you're starting the embedded container in a <span style="font-family: "Courier New",Courier,monospace;">main()</span> method, you would need to terminate the JVM explicitly.<br />
<h2>
Permgen space issues</h2>
The embedded EJB container of WLS is not as lightweight as I expected it to be. It runs into issues with the space allocated to the permanent generation consistently. I used the below listed JVM flag to boot up the JVM that eventually runs the embedded container, to make the problem go away.<br />
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<span style="font-family: "Courier New",Courier,monospace;">-XX:MaxPermSize=128M</span><br />
<br />
The JVM had a max heap utilization of ~300 MB, and a max perm gen size of ~100 MB for the deployment of a single SLSB. Apparently, other services were also started along with the EJB container, and I didn't find a way to prevent them from starting (maybe they are necessary).<br />
<br />
You may need to increase the heap-size as well as the permanent generation size if your application is larger.<br />
<h2>
Using an existing WLS domain</h2>
Note - this appears to be an undocumented feature at the moment. Use it at your own risk.<br />
<br />
The embedded EJB container creates a new WebLogic domain upon initialization; the domain is created in the "<span style="font-family: "Courier New",Courier,monospace;">java.io.tmpdir</span>" directory. Sometimes, you might want to use an existing WLS domain, especially if you'd like to cut down on startup time. This is possible, but the mechanism is very kludgy and requires some knowledge of the WLS container startup mechanisms.<br />
<br />
Unlike the GlassFish embedded container that supports usage of an existing GlassFish installation and instance, through the <span style="font-family: "Courier New",Courier,monospace;">setInstallRoot()</span> and <span style="font-family: "Courier New",Courier,monospace;">setInstanceRoot()</span> methods of the <a href="http://embedded-glassfish.java.net/nonav/apidocs/org/glassfish/embeddable/BootstrapProperties.html">BootStrapProperties</a> class, embedded WLS does not appear to have any documented/supported mechanism at the moment. However, a peek into the embedded container reveals a few things. The embedded EJB container looks for an existing WLS domain at the location defined by the "weblogic.RootDirectory" system property. Using this property one could point the embedded container to use a previously created WLS 12c domain, like so:<br />
<br />
<pre class="brush:java">System.setProperty("weblogic.RootDirectory", "/home/vineet/Oracle/Middleware/user_projects/domains/embedded_domain");
</pre>
<br />
This is still not sufficient though. The embedded container looks for a marker file ".embed-server-marker" at the root of the domain directory. An absence of the marker file will result in the container throwing an exception on startup. You can create a marker file in Linux, like so:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">touch ~/Oracle/Middleware/user_projects/domains/embedded_domain/.embed-server-marker</span><br />
<br />
<br />
Again, this is not sufficient to operate the embedded container with an existing domain. The boot identity would have to be passed to the container at startup. This is done via the "weblogic.management.username" and "weblogic.management.password" properties, like so:<br />
<br />
<pre class="brush:java">System.setProperty("weblogic.management.username","weblogic");
System.setProperty("weblogic.management.password","welcome1");
</pre>
<br />
Finally, (no, it's not over yet) you'll need to configure the domain to use a special startup class. In your $DOMAIN_HOME/config/config.xml file, add the following startup class that targets the admin server of your domain:<br />
<br />
<pre class="brush:xml"> <startup-class>
<name>embedded-server-startup-class</name>
<target>myserver</target>
<class-name>weblogic.server.embed.internal.EmbeddedServerStartupClass</class-name>
<failure-is-fatal>true</failure-is-fatal>
<load-after-apps-running>true</load-after-apps-running>
</startup-class>
</pre>
<br />
It is important to note that the Admin Server of the WLS domain is the one that is started in the embedded container. <br />
<br />
This is also the time to reflect on why the marker file created earlier is important - domains created by the embedded container are configured in a special way (with the startup class at a minimum), and are possibly not recommended for continuous development. My assumption is that using the embedded container against an existing domain might change the domain configuration in an irrevocable manner, and hence the absence of marker file protects a typical WLS domain from these changes.<br />
<br />Anonymoushttp://www.blogger.com/profile/13688757724895249188noreply@blogger.com1tag:blogger.com,1999:blog-10189396.post-40938884402839930762012-01-13T17:47:00.001+05:302012-01-13T17:47:23.549+05:30Starting WebLogic Server (10.3/11gR1) in debug modeThis is a mere note.<br />
When starting WebLogic Server using the startWebLogic script, the JDWP options for starting the server can be enabled, by setting the 'debugFlag' environment variable to true.<br />
<br />
The startWebLogic script examines the value of this environment variable to add the remote debugging flags to the JVM that it initializes.Anonymoushttp://www.blogger.com/profile/13688757724895249188noreply@blogger.com0tag:blogger.com,1999:blog-10189396.post-38511603210628894332011-10-05T23:20:00.000+05:302011-10-05T23:22:07.908+05:30Resolving the warning "Incorrect @Resource annotation class definition - missing lookup attribute" thrown by embedded Glassfish 3.1Running code in embedded Glassfish, where one uses the @Resource annotation, is quite a roller coaster. It is very typical to find the messages like the following, in the embedded Glassfish logs on running unit-tests deployed onto the embedded container from Glassfish:
<script type="syntaxhighlighter" class="brush: plain"><![CDATA[
5 Oct, 2011 11:03:18 PM org.glassfish.apf.impl.DefaultErrorHandler warning
WARNING: Incorrect @Resource annotation class definition - missing lookup attribute
symbol: FIELD
location: private javax.sql.DataSource org.jboss.arquillian.container.glassfish.embedded_3_1.app.MyServlet.arquillianDS
]]></script>
The solution to this is rather straightforward: one would need to add the Java EE 6 version of the @Resource annotation, instead of relying on the Java SE 6 provided class. Java EE 6 added the lookup attribute to the annotation. Quite obviously, annotation processing performed during execution of unit-tests in Java SE 6 would fail for this particular attribute, as the JDK simply lacks this new class. If you are running your tests using the Surefire plugin, you will need to configure the plugin to add the Java EE 6 jar containing the new class as an endorsed directory. Apparently, this is the approach adopted by Glassfish, where in the <code>modules/endorsed</code> directory under the Glassfish install root, is added as a Java endorsed library directory at startup. The same configuration, can be carried over to Surefire in the following manner:
<script type="syntaxhighlighter" class="brush: xml"><![CDATA[
...
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.10</version>
<configuration>
<!-- Adds directories from the local Maven repo containing certain internal
Glassfish dependencies, as endorsed directories for the Oracle/Sun JDK. This
will ensure that the warning "Incorrect @Resource annotation class definition
- missing lookup attribute" is not thrown by embedded Glassfish, as the JARs
in this endorsed dir have the Resource class required by embedded Glassfish. -->
<argLine>-Djava.endorsed.dirs=${settings.localRepository}/org/glassfish/javax.annotation/3.1/</argLine>
</configuration>
<dependencies>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.annotation</artifactId>
<version>3.1</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
...
]]></script>
The <code>org.glassfish:javax.annotation:3.1</code> dependency is from Glassfish 3.1.1 (build 12), and contains the Java EE 6 version of the Resource annotation. You may need to modify the version of this dependency, to suit your environment. Note, that the directory containing the dependency is located in the local Maven repository.
Also, you could perform similar changes to other Maven plugins that require the location of the JAR as a Java endorsed library directory, during JVM startup.Anonymoushttp://www.blogger.com/profile/13688757724895249188noreply@blogger.com0tag:blogger.com,1999:blog-10189396.post-14881022721040384692011-07-19T03:13:00.000+05:302011-10-05T22:57:57.737+05:30Starting Glassfish 3.1 in debug mode using the Glassfish Maven pluginI am documenting this for the sake of posterity. The <a href="http://maven-glassfish-plugin.java.net/">Maven Glassfish plugin</a> allows for starting and stopping Glassfish domains using Maven goals, apart from allowing for deployment, re-deployment and undeployment of applications.<br />
<br />
Until now, I never found the need to start Glassfish in the debug mode, thanks to the unit tests that I've been writing. However there are those times where remote debugging does help. Starting Glassfish in the debug mode using the Maven plugin is quite easy, especially if one has already created a domain. All one needs to do is to create a separate Maven profile to start Glassfish in the debug mode; specifying the debug parameter in the start-domain goal is sufficient to start Glassfish in the debug mode, for Glassfish enables JDWP using the options specified in the Glassfish domain configuration file.<br />
<br />
My Glassfish domain configuration file had the following <code>debug-options</code> attribute to enable remote debugging, and to allow for remote debuggers to connect onto port 9009:<br />
<br />
<script type="syntaxhighlighter" class="brush: xml"><![CDATA[
<java-config debug-options="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=9009" system-classpath="" classpath-suffix="">
]]></script><br />
<br />
Getting Glassfish to start in the debug mode from the maven plugin required passing in the <code><debug>true</debug></code> parameter, which automatically resulted in the debug options being used to start Glassfish. Under the hood, the <code>asadmin start-domain</code> command is executed with the <code>--debug=true</code> option which eventually results in Glassfish starting in the debug mode. Following is the snippet from my Maven POM file, containing the relevant configuration:<br />
<br />
<script type="syntaxhighlighter" class="brush: xml; highlight: [28]"><![CDATA[
<project>
...
<profiles>
<profile>
<id>remote-debug</id>
<build>
<plugins>
<plugin>
<groupid>org.glassfish.maven.plugin</groupId>
<artifactid>maven-glassfish-plugin</artifactId>
<version>2.1</version>
<configuration>
<user>admin</user>
<passwordfile>C:/glassfish3/glassfish/domains/domain1/config/local-password</passwordFile>
<glassfishdirectory>C:/glassfish3/glassfish/</glassfishDirectory>
<components>
<component>
<name>${project.artifactId}</name>
<artifact>${project.build.directory}/${project.build.finalName}.ear</artifact>
</component>
</components>
<domain>
<name>domain1</name>
<adminport>4848</adminPort>
<httpport>8080</httpPort>
<httpsport>8443</httpsPort>
</domain>
<debug>true</debug>
<echo>true</echo>
<terse>false</terse>
<autocreate>false</autoCreate>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
...
</project>
]]></script><br />
<br />
Note line 28 which triggers the debug mode and gets Glassfish to use the JDWP options. Apparently, the Maven Glassfish plugin also supports this curiously named "jvmOptions" parameter. This parameter is ignored for all practical purposes when starting a domain. In reality, it is used in the limited scenario of creating a new domain; the Maven Glassfish plugin uses the jvmOptions parameter to create a jvmOption for a domain in domain.xml; under the hood, the plugin executes the "asadmin create-jvm-options ..." command with the parameters to the create-jvm-options command being constructed from the jvmOptions parameter in the Maven POM.<br />
<br />
Using the previously created Maven profile to start Glassfish is quite easy:<br />
<br />
<script type="syntaxhighlighter" class="brush: plain"><![CDATA[
mvn glassfish:start-domain -P remote-debug
]]></script><br />
<br />
will do the needful activity of using the defined Maven profile.Anonymoushttp://www.blogger.com/profile/13688757724895249188noreply@blogger.com0tag:blogger.com,1999:blog-10189396.post-84961435342175190852011-07-18T18:24:00.000+05:302011-07-18T18:24:57.432+05:30Configure Hibernate logging on Glassfish with SLF4JGlassfish 3.1 ships with EclipseLink as the default JPA provider. One can, however, install Hibernate 3.5 using the Glassfish Update Tool, which is the easiest means of installing Hibernate on Glassfish. The installation also installs the SLF4J-JDK14 wrapper, that will enable all SLF4J logging calls to be redirected to the <code>java.util.logging</code> logging implementation used by Glassfish. One would, therefore, find that SLF4J calls would be transparently redirected to the Glassfish domain log, without a lot of configuration.<br />
<br />
In order to configure logging for Hibernate on Glassfish, the JDK logger configuration in the <code>logging.properties</code> file of the Glassfish domain must be modified, to include any desired configuration changes. Simply put, one need not install log4j and the slf4j-log4j12 module in Glassfish and also provide log4j.properties to get Hibernate logging to work.<br />
<br />
The following lines were added in the <code>logging.properties</code> file of the Glassfish domain (usually located in <code>$GLASSFISH_DOMAIN/config</code>) to enable various loggers created by to provide a more verbose output:<br />
<br />
<script class="brush: plain" type="syntaxhighlighter">
<![CDATA[
# Hibernate configuration
org.hibernate.level=INFO
org.hibernate.hql.ast.AST.level=INFO
org.hibernate.SQL.level=FINE
org.hibernate.type.level= FINE
org.hibernate.tool.hbm2ddl.level=INFO
org.hibernate.engine.level=FINE
org.hibernate.hql.level=FINE
org.hibernate.cache.level=INFO
org.hibernate.jdbc.level=FINE
]]>
</script><br />
<br />
To understand how those entries work, it is sufficient to understand that Hibernate uses SLF4J as a logging facade, delegating the actual writing of the log records to an underlying logger like log4j, logback or the JDK logger. Glassfish uses the JDK logger as the logging implementation, and to enable the calls on the SLF4J logger, to create entries in the Glassfish domain logs, one must have the SLF4J-JDK14 module (slf4j-jdk14-x.y.z.jar) installed in the classpath. The <a href="http://www.slf4j.org/api/org/slf4j/impl/JDK14LoggerAdapter.html">SLF4J-JDK14 module</a> serves to adapt all SLF4J method calls to the JDK Logger interface, allowing any application (in this case, Hibernate) using SLF4J to have the log records written by the JDK logger. The adapter transforms the levels used by SLF4J to the ones known to the JDK logger as follows:<br />
<br />
<table> <thead>
<tr>
<td><b>SLF4J Level</b></td>
<td><b>JDK Logger Level</b></td>
</tr>
</thead>
<tbody>
<tr>
<td>TRACE</td><td>FINEST</td>
</tr>
<tr>
<td>DEBUG</td><td>FINE</td>
</tr>
<tr>
<td>INFO</td><td>INFO</td>
</tr>
<tr>
<td>WARN</td><td>WARNING</td>
</tr>
<tr>
<td>ERROR</td><td>SEVERE</td>
</tr>
</tbody>
</table><br />
By inference, an invocation within Hibernate using <code>Logger.trace()</code> would be logged only if the JDK logger was configured to log messages at the FINEST level.Anonymoushttp://www.blogger.com/profile/13688757724895249188noreply@blogger.com2tag:blogger.com,1999:blog-10189396.post-85508681778748360052011-07-09T08:51:00.000+05:302011-07-09T08:58:22.091+05:30Building a dynamic image based carousel with PrimeFaces 2.2.1Time for another demonstration. This time, I needed to build a carousel with data including text and images. And, I chose to use the PrimeFaces carousel component for this purpose. The code presented here is available for download at my <a href="https://bitbucket.org/VineetReynolds/primefaces-carousel-demo">BitBucket repository</a>.<br />
<br />
Building a carousel with the PrimeFaces component is quite easy if you can not embedding rich and dynamic content within the carousel. The PrimeFaces User Guide downloadable off the <a href="http://www.primefaces.org/documentation.html">PrimeFaces documentation page</a>, does contain an example to get you started. I will extend that example to demonstrate how to use the StreamedContent class to enable display of images that could possibly be stored in a database or in a content management system.<br />
<br />
The user interface layout of the desired final outcome is shown below.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgB5DWLLzc_ahEcFIHOFlyUygdE-l2RWYsGYdHCfAtF3Cmch-bRVQjW52_ytlKFVE8rTOQQ46IVfsAfiP67LVLZ9UGAU_nqkjT18lKgNT81xN6vnRjtECanMp1Sy8SSMAUUuq4kbw/s1600/Carousel+-+Layout.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="265" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgB5DWLLzc_ahEcFIHOFlyUygdE-l2RWYsGYdHCfAtF3Cmch-bRVQjW52_ytlKFVE8rTOQQ46IVfsAfiP67LVLZ9UGAU_nqkjT18lKgNT81xN6vnRjtECanMp1Sy8SSMAUUuq4kbw/s400/Carousel+-+Layout.png" width="400" /></a></div><br />
The intent is to demonstrate how to display non-static content in the carousel. This is easy for text content as the carousel component supports the embedding of <code>h:outputText</code> tags and iteration through a collection using the <code>var</code> attribute. The example in the PrimeFaces user guide already covers this. We'll be looking at the use of the <code>f:param</code> tag to iterate through a collection of StreamedContent objects. To make things simple, we will be reading images off files instead of BLOB objects in a database, or similar binary input streams.<br />
<br />
<h3>The Facelet</h3><br />
We will start by designing the facelet page that will use the carousel component. The code for the facelet is listed below:<br />
<br />
<script class="brush: xml" type="syntaxhighlighter">
<![CDATA[
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.prime.com.tr/ui">
<f:loadBundle var="msg" basename="resources.messages" />
<h:head>
<title><h:outputText value="#{msg.title}" />
</title>
</h:head>
<h:body>
<div>
<p:carousel id="photo-carousel" value="#{imageBean.images}"
var="image" rows="3">
<h:panelGrid cellpadding="5" style="width: 266px; height: 200px;"
columns="1">
<p:graphicImage value="#{photoStreamer.fileContent}">
<f:param id="photo_id" name="photo_id" value="#{image.id}" />
</p:graphicImage><h:outputText value="#{image.title}" />
<h:outputText value="#{image.description}" />
</h:panelGrid>
</p:carousel></div></h:body>
</html>
]]>
</script><br />
<br />
The carousel definition contains:<br />
<br />
<ul><li> a collection of items that used to render each individual item in the carousel. This is specified using the <code>value="#{imageBean.images}"</code> expression. For all practical purposes, the carousel is similar to a <code>h:dataTable</code> component as far as this attribute is concerned. Without specifying a <code>value</code> attribute that is referenced by a collection, one cannot render a collection of items in the carousel, whose size is unknown at design time. We'll see the definition of the managed bean class <code>ImageBean</code> later.<br />
</li>
<li> a name to reference an element in the above defined item collection. This is similar to the <code>var</code> attribute of the <code>h:dataTable</code> component. In the above facelet, <code>var="image"</code> is used to create a temporary reference to every item in the <code>images</code> collection of the <code>ImageBean</code> class.<br />
</li>
a panel grid that is used to act as a container for the image, the title and the description of the image. It contains a <code>style</code> attribute whose usage is described later.
<li> a PrimeFaces <code>p:graphicImage</code> component that is used to stream the image back to the browser. Note the use of the <code>f:param</code> tag. The <code>p:graphicImage</code> component cannot use the temporary reference created by the <code>var</code> attribute of the carousel component. The <code>value</code> attribute must evaluate to a StreamedContent object, but more importantly the <code>p:graphicImage</code> component will be rendered as a <code>img</code> tag with a <code>src</code> attribute containing a URL that will be used by the browser to fetch the image (present in a StreamedContent object). This URL does not change across the items in the carousel, and hence a parameter must be passed to identify the image being requested. This is done using the <code>value="#{image.id}"</code> attribute of the parameter that is used to pass a parameter of name <code>photo_id</code>. We shall see how this parameter is parsed by another Managed Bean, in a later section of the article.<br />
</li>
<li> a couple of <code>h:outputText</code> components that are used to display the title and description items. These use the reference created by the <code>var</code> attribute, and unlike the <code>p:graphicImage</code> component there are no issues involving the use of the temporary reference in this case.<br />
</li>
</ul><br />
<h3>The Managed Bean for the carousel component</h3><br />
The managed bean used to manage the collection of images is listed below:<br />
<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
package info.example.view;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ManagedBean
@RequestScoped
public class ImageBean
{
public static final int MAX_IMAGE_COUNT = 15;
private static final Logger logger = LoggerFactory.getLogger(ImageBean.class);
private List<photo> images;
public ImageBean()
{
images = new ArrayList<photo>();
for (int ctr = 0; ctr < MAX_IMAGE_COUNT; ctr++)
{
Photo photo = new Photo();
photo.setId(ctr);
photo.setTitle("Mock Title #" + ctr);
String description = "This photo is used to represent item #" + ctr + " in a selection of images.";
photo.setDescription(description);
images.add(photo);
logger.info("Added Photo {} to collection.", ctr);
}
}
public List<Photo> getImages()
{
return images;
}
public void setImages(List<photo> images)
{
this.images = images;
}
}
]]>
</script><br />
<br />
The class is quite simple in design, in that it is used to store a reference to a list of <code>Photo</code> objects that contains merely the text content (title and description) of every image in the carousel. The <code>Photo</code> class is listed below. Again, it is quite simple in design, and is merely a bean class. Note the declaration of the <code>id</code> attribute of the class; this is used by the carousel component to provide the parameter to the <code>p:graphicImage</code> component.<br />
<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
package info.example.view;
public class Photo
{
private Integer id;
private String title;
private String description;
public Photo()
{
}
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
this.id = id;
}
public String getTitle()
{
return title;
}
public void setTitle(String title)
{
this.title = title;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
}
]]>
</script><br />
<br />
<h3>The Managed Bean for the graphicImage component</h3><br />
The managed bean class that is responsible for serving image requests is listed below.<br />
<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
package info.example.view;
import java.io.InputStream;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ManagedBean
@RequestScoped
public class PhotoStreamer
{
private static final Logger logger = LoggerFactory.getLogger(PhotoStreamer.class);
private static StreamedContent defaultFileContent;
private StreamedContent fileContent;
public StreamedContent getFileContent()
{
logger.trace("Entered method getFileContent.");
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
String photoId = externalContext.getRequestParameterMap().get("photo_id");
if(photoId == null || photoId.equals(""))
{
fileContent = defaultFileContent;
logger.info("Id was null or empty. Retrieved default file content.");
}
else
{
int parsedId = Integer.parseInt(photoId);
if(parsedId < 0 || parsedId > ImageBean.MAX_IMAGE_COUNT)
{
fileContent = defaultFileContent;
logger.info("Invalid Id. Retrieved default file content.");
}
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
InputStream inputStream = contextClassLoader.getResourceAsStream("resources/images/Photo - " + parsedId + ".png");
fileContent = new DefaultStreamedContent(inputStream, "image/png");
logger.info("Retrieved file content for image {}.", parsedId);
}
logger.trace("Exited method getFileContent.");
return fileContent;
}
public void setFileContent(StreamedContent fileContent)
{
this.fileContent = fileContent;
}
static
{
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
InputStream inputStream = contextClassLoader.getResourceAsStream("resources/images/Photo - 0.png");
defaultFileContent = new DefaultStreamedContent(inputStream, "image/png");
}
}
]]>
</script><br />
<br />
This is obviously the class that allows the carousel to obtain images dynamically, so a more descriptive explanation of it's behavior is provided.<br />
<br />
Note that this class is a request scoped bean. Every image added in the carousel using the <code>p:graphicImage</code> tag will result in a separate GET request for the image. Once the image contents has been dispatched to the browser, the managed bean is no longer needed, unless the carousel needs to be rendered once again. It also not good design to store references to <code>StreamedContent</code> objects beyond a single request. Therefore, this class is not designed to be a session scoped class.<br />
<br />
The following snippet is used to parse the parameter passed to the bean via the <code>f:param</code> tag.<br />
<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
String photoId = externalContext.getRequestParameterMap().get("photo_id");
]]>
</script><br />
<br />
It is important to know that the value of the <code>photoId</code> variable can be null, even if the browser has not issued a request with a null photoId. This needs to be handled by creating a StreamedContent object that points to a "default" image, as show in the following snippet.<br />
<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
if(photoId == null || photoId.equals(""))
{
fileContent = defaultFileContent;
logger.info("Id was null or empty. Retrieved default file content.");
}
]]>
</script><br />
<br />
The <code>defaultFileContent</code> variable is a static variable that is initialized on loading of the class. The initialization process isn't exactly production quality, and one might consider adding exception handling to address this in a better manner. But for now, it would suffice to know that the <code>getFileContent</code> method should not return null. Apparently, the method is invoked during the Render Response phase and it is quite possible that the value of photoId is null, thereby necessitating the need to return a non-null <code>StreamedContent</code> object. The "default" image is also returned in the event of an image Id being incorrect (out of bounds in this case).<br />
<br />
Finally, if the image Id is valid, the context class loader is used to obtain a reference to a input stream that can be used to construct the <code>StreamedContent</code> object as demonstrated below:<br />
<br />
<script class="brush: java" type="syntaxhighlighter">
<![CDATA[
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
InputStream inputStream = contextClassLoader.getResourceAsStream("resources/images/Photo - " + parsedId + ".png");
fileContent = new DefaultStreamedContent(inputStream, "image/png");
]]>
</script><br />
<br />
In a production application, you would obviously be fetching the images from a database, a content management system, or from disk. In either case, you will need to obtain an <code>InputStream</code> object and use it to construct the <code>StreamedContent</code> object.<br />
<br />
<h3>Styling the carousel</h3><br />
The carousel component uses the YUI carousel component to render the actual carousel in the browser. It relies on some JavaScript goodness to set the sizes of the individual items in the carousel on loading the document. If the height and width of the items is not specified, then it is quite possible that the items will not be displayed correctly; it is quite possible to have the items overflow each other. The YUI carousel requires that the <code>height</code> and <code>width</code> values be specified on each item (<code>li</code>0 in the list (<code>ol</code>) that is generated. Hence, it is necessary to set the style in the <code>h:panelgrid</code> component as follows:<br />
<br />
<script class="brush: xml" type="syntaxhighlighter">
<![CDATA[
<h:panelGrid cellpadding="5" style="width: 266px; height: 200px;" columns="1">
]]>
</script><br />
<br />
<h3>Other interesting stuff</h3><br />
<ul><li> The carousel described above displays correctly in all modern browsers except IE 9 where it is quite horribly broken (even in compatibility mode, where the YUI carousel appears to work). This might require a revision to the posted code.<br />
</li>
<li> The PrimeFaces carousel automatically offers a drop down if the number of items exceeds 5 pages. At least that was my observation. Quite obviously, the carousel is not meant to be used in scenarios where a lot of items are present in a collection.<br />
</li>
<li> The images in the carousel are fetched upfront on initial document load, and not when pagination occurs. Other components would therefore be suitable if the number and size of the images exceeds a limit where performance becomes a problem; this would vary from application to application.<br />
</li>
<li> The icons used in the project are from the <a href="http://webtoolkit4.me/2009/03/17/polaroid-icon-set/">Polaroid icon set</a>.<br />
</li>
</ul>Anonymoushttp://www.blogger.com/profile/13688757724895249188noreply@blogger.com5tag:blogger.com,1999:blog-10189396.post-47566312723601482992011-06-29T05:14:00.000+05:302011-06-29T05:15:22.822+05:30File uploads with PrimeFaces v2.2.1I've been working on a few Java EE 6 applications using JSF 2.0 for a while now, and my experience with the default implementation within Glassfish 3.1 - <a href="http://javaserverfaces.java.net/">Mojarra</a> has left me wanting for more. One of my applications required a file upload widget. <a href="http://balusc.blogspot.com/2009/12/uploading-files-with-jsf-20-and-servlet.html">This is doable in Mojarra</a> but requires a shim. I decided to create a spike implementation using <a href="http://www.primefaces.org/">PrimeFaces</a>, since that apparently had a fileUpload component; the spike obviously being used to estimate the time I would require to port the application to PrimeFaces.<br />
<br />
A few minutes later, and I managed to get a working example up and running. The example is based on several similar examples posted on the internet. I've attempted to document a couple of gotchas encountered.<br />
<br />
<b>The Source Code</b><br />
<br />
This was my JSF page; it is quite simple. The <a href="http://primefaces.prime.com.tr/docs/tag/p/fileUpload.html">fileUpload</a> component was made available on adding the primefaces tag. Note the use of the h:head tag. Apparently, PrimeFaces will add scripts and stylesheet resources with the target value set to "head". If one uses the plain head tag from the xhtml namespace, then the scripts and stylesheets will not be added.<br />
<br />
<script type="syntaxhighlighter" class="brush: xml"><![CDATA[
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.prime.com.tr/ui">
<f:loadBundle basename="resources.application" var="msg"/>
<h:head>
<title><h:outputText value="#{msg.welcomeTitle}" /></title>
</h:head>
<body>
<h3>
<h:outputText value="#{msg.welcomeHeading}" /></h3><p>
<h:outputText value="#{msg.welcomeMessage}" /></p><h:form enctype="multipart/form-data">
<p:growl id="messages" showSummary="true" showDetail="false" />
<p:fileUpload id="fileuploader"
multiple="false" fileUploadListener="#{fileUploadBean.handleFileUpload}"
update="messages" label="#{msg.chooseText}" description="#{msg.descriptionText}"
allowTypes="*.jpg;*.gif;*.png;"
/>
</h:form>
</body>
</html>
]]></script><br />
<br />
One can notice similarities between the above facelet and <a href="http://technology.amis.nl/blog/6817/getting-started-with-primefaces-on-glassfish-v3">the one posted on the AMIS blog</a>, which was followed during the spike.<br />
<br />
The managed bean that processes the FileUploadEvent is quite simple. My current need of the hour was to extract the contents of the uploaded file into a byte array to persist into a BLOB in a database; this was duly supported by the UploadedFile class of PrimeFaces.<br />
<br />
<script type="syntaxhighlighter" class="brush: java"><![CDATA[
package com.example;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.UploadedFile;
@ManagedBean
@RequestScoped
public class FileUploadBean
{
private static final Logger logger = Logger.getLogger(FileUploadBean.class.getName());
public void handleFileUpload(FileUploadEvent event)
{
UploadedFile file = event.getFile();
String fileName = file.getFileName();
byte[] fileBytes = file.getContents();
logger.log(Level.INFO, "Processed uploaded file " + fileName + " of size:" + fileBytes.length);
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "The file was uploaded successfully.", null);
FacesContext.getCurrentInstance().addMessage(null, message);
}
}
]]></script><br />
<br />
And finally, to top it off, here are the contents of the deployment descriptor and the resource bundle.<br />
<br />
<script type="syntaxhighlighter" class="brush: xml"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>FileUploadSpike</display-name>
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name><param-value>server</param-value></context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<filter>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
<init-param>
<param-name>thresholdSize</param-name><param-value>51200</param-value></init-param>
</filter>
<filter-mapping>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
</web-app>
]]></script><br />
<br />
<script type="syntaxhighlighter" class="brush: plain"><![CDATA[
# -- welcome --
welcomeTitle=PrimeFaces fileUpload Spike Application
welcomeHeading=Welcome!
welcomeMessage=This is a PrimeFaces example application. \
This is an example of the PrimeFaces fileUpload component.
chooseText=Choose a file
descriptionText=Image files
]]></script><br />
<br />
<b>Deployment</b><br />
<br />
PrimeFaces 2.2.1 depends on Commons FileUpload 1.2.1 and Commons IO 1.4 to provide the file upload functionality; one can find the details of the dependencies in the packaged pom.xml of the PrimeFaces distribution. Anyone using Maven will quite obviously not have to bother about this, but for those who do not, it is quite obvious that the files commons-fileupload-1.2.1.jar, commons-io-1.4.jar and primefaces-2.2.1.jar have to be placed in the WEB-INF/lib directory of the packaged WAR file, in case these are not provided by the container.Anonymoushttp://www.blogger.com/profile/13688757724895249188noreply@blogger.com3tag:blogger.com,1999:blog-10189396.post-1150636621141630442006-06-18T18:35:00.000+05:302010-08-13T02:57:10.195+05:30Investment lessons in a single picture<a href="http://photos1.blogger.com/blogger/4368/776/1024/investment.jpg"><img alt="" src="http://photos1.blogger.com/blogger/4368/776/400/investment.jpg" border="0" /></a><br /><br />Demonstrated to me by my banker friend Manmohan, at my new company. Fairly self explanatory.<br /><br /><br />Summarized as follows,<br /><ul><li>The chance of higher earnings/profit increases with more riskier investments.<br /></li><li>The moment a person gets better earnings from an investment destination, the risk in investing w.r.t that destination virtually reduces, and it is wise to put in/ transfer more investments to that destination.<br /></li><li>The bulk of investments should be in the least risky of all investment destinations.</li>It is generally better to put money in an investment destination where the principal amount is guaranteed to be returned. Direct equities and mutual funds are therefore not recomended as good investment destinations unless well understood.</ul> <a href="http://picasa.google.com/blogger/" target="ext"><img src="http://photos1.blogger.com/pbp.gif" alt="Posted by Picasa" style="border: 0px none; padding: 0px; background: none repeat scroll 0% 50% transparent;" align="middle" border="0" /></a>Anonymoushttp://www.blogger.com/profile/13688757724895249188noreply@blogger.com4tag:blogger.com,1999:blog-10189396.post-1145372659119759322006-04-18T20:35:00.000+05:302006-05-08T01:39:08.990+05:30iText + Google Calendar = Neat Printouts!!<div xmlns="http://www.w3.org/1999/xhtml"><br /><a href="http://img510.imageshack.us/img510/8678/googcalendar7ks.jpg"><img src="http://img510.imageshack.us/img510/8678/googcalendar7ks.jpg" alt="Google Calendar" width="100%" /></a><br /><br /><a href="http://www.jroller.com/page/blowagie?entry=itext_used_in_google_calendar">Google Calendar (beta at time of writing) uses an Open Source library iText for printing calendars</a>. The calendars are generated as PDF files that can be downloaded to the desktop or straightaway printed.<br />And this is for the programmers who work under pointy haired Dilberty bosses - the next time you're asked for internet based silent printing of PDF files, ask them to have a look at Google Calendar. You can't get more professional than that. Want anything better? You should think of writing your own proprietary browser (i.e a desktop app) or browser plugin or a Acrobat Reader plugin. Good luck buddy.<br /><br />Technorati Tags: <a href="http://technorati.com/tag/google+calendar" rel="tag">google+calendar</a>, <a href="http://technorati.com/tag/itext" rel="tag">itext</a></div>Anonymoushttp://www.blogger.com/profile/13688757724895249188noreply@blogger.com0tag:blogger.com,1999:blog-10189396.post-1138960208179924912006-02-26T18:00:00.000+05:302006-11-15T21:48:57.500+05:30Adobe Acrobat 7.0 Browser Control Type Library (ActiveX or COM)<span style="font-weight: bold;">Update</span>: Please check out the other PDF related links in the sidebar as well.<br /><br />Some horrors are erased!! Gasp !!<br /><br />I came across the Adobe Acrobat 7.0 Browser Control Type Library that could be used to display and print PDF files on desktop (Windows forms) applications [I haven't explored utilizing this in a webpage, so that will have to wait]. This is really good stuff for some people, for it is an ActiveX control that you could utilize to automate certain PDF-related actions, instead of relying on the AcroRd32.exe process commandline options or DDE messaging (or worse - Win32 programming).<br /><br />However, every approach has it's pitfalls.<br />And <a href="http://channel9.msdn.com/ShowPost.aspx?PostID=155079#155079">someone's already had a problem</a> -<br /><blockquote><br />Bah. I can't believe that Adobe hasn't stepped up to hand out a library that will print any PDF with all of the printer settings available to be changed. (You apparently can create an Interop around their Acrobat TypeLib, but its features are limited and it can only print to the default printer.)<br /><br />Oh well, that's why folks can charge lots of money for libraries I guess.</blockquote><br /><br />And if you have funds, then take this advice from an ex-Adobe employee a bit seriously, for he says -<blockquote><br />I can give ya a little info on this as a former Adobe Employee and specifically dealing with Acrobat. They do have a SDK that allows you to work with PDFs but its not free, it does work in both managed and unmanaged code and they give some good examples done in C# and VB.net but here again its not free. I would look to some of the free PDF stuff and that may work but this is workable if you have the SDK because you can actually create a PDF object and load in that PDF and then use c# to print it like you would anything else.</blockquote><br />Here's <a href="http://www.codeproject.com/miscctrl/acroview.asp">the CodeProject article utilizing the Adobe Acrobat 7.0 ActiveX object</a> for communicating with Acrobat Reader, along with <a href="http://www.codeproject.com/miscctrl/acroview.asp?df=100&forumid=151712&select=1091073#xx1091073xx">the .Net example utilizing the Browser Type Library</a> that is described in the comments.<br /><br />Ok, want to know more about this library ? Hop on and download the <a href="http://partners.adobe.com/public/developer/en/acrobat/sdk/pdf/iac/IACReference.pdf">Adobe Acrobat Inter-Application Communication (IAC) Reference from the Adobe site (pdf download)</a>. The Acrobat Browser Type Library is provided by the <b>AxAcroPDFLib.AxAcroPDF</b> object. This should be suitable for most of your needs. You can access it by adding a reference to AcroPDF.dll (that resides in the ActiveX directory under the Acrobat application directory) in your IDE environment.<br /><br /><i><b>Technical Notes</b></i><br /><ul><li>If you dont want to display the PDF document in a Windows Forms application, then you'll have to set the 'Visible' property to false. And if you want to send the PDF file directly to the printer, then you could use one of the methods provided by the control for that purpose - Print, PrintAll, PrintAllFit, PrintPages, PrintPagesFit. That should be suitable for your silent print needs in most cases.<br /></li><li>You could experience problems when you have to print to the default printer. The default printer seem to be determined by Acrobat when it is loaded, and not by Windows. So changing the default printer mid-way through your application's runtime might cause unexpected behavior.</li><li>It is impossible to "name" / "determine" the printer that is used to print the document. Unless you don't want the user to access all the printer settings that could change the workflow, the only solution is to use the PrintWithDialog method (which is used to present the Acrobat Print Dialog Box that allows the user to make changes to the number of copies to be printed, or print to a file).<br /></li></ul><br />And to help people searching for solutions to common problems involving Adobe Acrobat (even Reader), I'm posting a link to <a href="http://www.experts-exchange.com/Web/Graphics/Adobe_Acrobat/Top_Solutions_1.html">Experts Exchange's set of time-tested Adobe Acrobat solutions</a>.<br /><br /><div class="techtags">Tech Tags: <a href="http://technorati.com/tag/Adobe" rel="tag" class="techtag">Adobe</a> <a href="http://technorati.com/tag/Acrobat" rel="tag" class="techtag">Acrobat</a> <a href="http://technorati.com/tag/ActiveX" rel="tag" class="techtag">ActiveX</a> <a href="http://technorati.com/tag/type+library" rel="tag" class="techtag">type+library</a> <a href="http://technorati.com/tag/print" rel="tag" class="techtag">print</a> <a href="http://technorati.com/tag/PDF" rel="tag" class="techtag">PDF</a> </div>Anonymoushttp://www.blogger.com/profile/13688757724895249188noreply@blogger.com9tag:blogger.com,1999:blog-10189396.post-1140373992645673292006-02-19T23:58:00.000+05:302006-05-08T00:40:12.210+05:30Internet based silent print using scripting languages (client side scripting). Why doesnt it work?<span style="font-weight: bold;">Update</span>: Please do not forget to check the other PDF related links in the sidebar<br /><br /><br /><span style="font-weight: bold; font-style: italic;">Backdrop:</span><br /> You want to allow your site visitors or customers to print documents without popping up a dialog box. You dont want to display a print dialog box because you feel it's a distraction or a devaition from normal website browsing flow. You're probably right in asking for a silent print feature in the browser object model, especially in the model provided by JavaScript (or any client side scripting language).<br /><br />In this short article (that would be extended later on, depending on how many people read it and find it useful), I will detail why the browser model doesnt allow for silent printing , or automatic printing over an Internet-based website, with minimum or no user interaction.<br /><span style="font-weight: bold; font-style: italic;"><br />Let's get into the details . . . . .</span><br /> Basically, the job of the browser is to display webpages. Technically, this means that the browser is supposed to do only certain types of jobs - display HTML and allow for user-interaction with dynamic elements in the webpage. The browser is not allowed to do certain things by default - execute a snippet of code, download files that it doesnt understand or recognize, create system files that would execute in the background and log user activity.<br /><br />You could extend the browser through plugins to do some of those jobs. You could write scripts in client-side scripting languages to perform "certain" tasks at the client's computer. But client side scripting languages would have limitations on what a scripter is able to command the client's browser to do.<br /><br />That's purely because of the nature of the Internet - it's not a trusted zone.<br /><span style="font-weight: bold; font-style: italic;">What's a trusted zone ?</span><br /> Well, basically it is a place where all the accessible resources are trusted by your computer (indirectly, you trust the resources at the place). It could be the local area network (so long as you're sure that your computer will be secure in it), or the network of your business associate or subsidary (as long as you chose to trust the resources availble on the foreign network).<br /><br /><br /><span style="font-weight: bold; font-style: italic;">So what's the thing with trusted zones and untrusted zones ?</span><br /> Trusted zones as the name says are places trusted by the client. The resources in such a place are capable of interacting with the resources at the client's place. The degree of such interaction depends totally on the nature and degree of the trust. For example, you trust that executables residing on your own drive/computer are far more trustworthy than the ones you downloaded off www.hackers.com .<br /><br /><br /><span style="font-weight: bold; font-style: italic;">How does this affect automatic printing ? Or, why should this concern me ?</span><br /> Code running in trusted environments have far more privileges than code running from an untrusted source. For example, executables in your computer are capable of deleting certain files from the hard disk, but code running in the browser will not be capable of doing so (until the user has granted that privilege). Printing, or better, automated printing requires that the end-user grant privileges to your code to access his/her printer (that's the user's printer not yours). The remote printer is a resource that belongs to the remote computer to which it is plugged into (even though, your office may have paid for it). To access the remote printer, it is required that the remote computer grant privileges to your code to access the remote printer.<br /><br /><br /><span style="font-weight: bold; font-style: italic;">Hell, I dont need privileges to access the remote printer. My boss says that the client trusts our website so the client should be able to print without any user interaction . Why I should believe you ?</span><br /> There are websites out there that are capable of ruining your client's computer, so why not yours ? Is there anything special about your site ? And how does the client know that you are not using his printer to print advertisements (of no value to him) ?<br /> And what is with the minimum user-interaction ? How are you so sure that the printer will always print the correct output ? What if something went wrong during printing ? Why does your client have a problem clicking a button in the print dialog box ?<br /> The print dialog is there to -<br /><ul><li>grant access to your instructions to issue a print command,</li><li>allow the user to modify any necessary settings that are necessary for obtaining a successful printout.</li></ul><br /><span style="font-weight: bold; font-style: italic;">I know of an environment where you're wrong !!</span><br /> It's probably on ActiveX based websites. Nothing new there. ActiveX is known to be insecure, and is supported only on MS Internet Explorer. Dont be surprised if half of your users wont be able to access your website.<br /> If you're talking about Java(not JavaScript), then again there is nothing new there. If you are able to produce a signed applet, then it is possible to automate the print process as much as possible. It's mileage depends on what libraries you are using, that is, how powerful the libraries are in their ability to access the printer options, and produce a clean printout with most of the settings provided by the programmer (that is, you) , and hence result in lesser user-interaction (because most of the settings are provided by the programmer).<br /> There is also a possibility of Winforms applications being able to print over the Internet. Like the first option mentioned above, Winforms applications seems to work only on Microsoft Internet Explorer. Unlike ActiveX, Winforms applications written using the .Net framework are far more secure. The programmer can request for further privileges to be granted to the code during it's execution. So, if your program wants to access the printer, it must merely request for the necessary privileges. Of course, the user executing the program has to grant the privileges. But this is far better than having a code "lockout" - your code is unable to run because it cannot even request for such privileges; your client will have to explicitly make changes to his computer's configuration to allow it run.<br /><br /><br /><span style="font-weight: bold; font-style: italic;">What now?</span><br /> Silent printing may be the tip of the iceberg. There are far more things that may not be possible using client side scripting languages. Most of them are not even things that should be solved using client side scripting. It's more an issue of whether people have analysed the business problem at hand, and have recognized that a browser based solution may not be the answer. Chances are that poorly architected and poorly designed solutions often call the limits of Javascript (and other scripting languages) into question. In most cases, the solution might be a Windows forms solution (or a background service or a cron job or . . . . . ), or sometimes a change in the business process (hah!).Anonymoushttp://www.blogger.com/profile/13688757724895249188noreply@blogger.com1tag:blogger.com,1999:blog-10189396.post-1138366997767375692006-01-27T18:26:00.000+05:302006-11-12T22:18:59.660+05:30Command line printing for Acrobat Reader<span style="font-weight: bold;">Update</span>: Please check the other PDF and print related links in the sidebar<br /><br /><br />The command line options for Adobe Acrobat (Reader, Standard and Professional) are unsupported and undocumented features.<br />They're never mentioned anywhere in the documentation provided by Adobe except for the Acrobat Developer FAQ.<br />Here is the link to the <a href="http://partners.adobe.com/public/developer/en/acrobat/sdk/pdf/intro_to_sdk/DeveloperFAQ.pdf">Acrobat Developer FAQ (pdf file)</a> that contains some documentation for using command line options; the relevant information can be found at the end of the document in page 27.<br />There's a warning though (and it's from Adobe) :<br /><blockquote>"These are unsupported command lines, but have worked for some developers. There is no documentation for these commands other than what is listed."</blockquote>God speed with your quest.<br /><br /><br /><div class="techtags">Tech Tags: <a href="http://technorati.com/tag/Adobe" rel="tag" class="techtag">Adobe</a> <a href="http://technorati.com/tag/Acrobat" rel="tag" class="techtag">Acrobat</a> <a href="http://technorati.com/tag/command+line" rel="tag" class="techtag">command+line</a> <a href="http://technorati.com/tag/developer+FAQ" rel="tag" class="techtag">developer+FAQ</a> </div>Anonymoushttp://www.blogger.com/profile/13688757724895249188noreply@blogger.com2tag:blogger.com,1999:blog-10189396.post-1137787768104266642006-01-20T23:45:00.000+05:302008-04-05T21:30:38.167+05:30Silent print a PDF file in Acrobat Reader (for PDF files served on the Internet)<span style="font-weight: bold;">Update</span>: Please do not forget to check the other PDF and print related links in the sidebar<br /><br /><br />Some of you might have been awaiting this.<br />You maybe disappointed with the results of this article though, so dont expect too much - I'll explain what is possible with existing software and code ( but not <a href="http://en.wikipedia.org/wiki/Voodoo_programming">voodoo programming</a> : that's not the kind of code that's bug free ).<br /><span class="fullpost"><br /><span style="font-weight: bold;font-size:130%;" >Prerequisites</span><br /><ul><li>Acrobat Javascript Guide (<a href="http://partners.adobe.com/public/developer/en/acrobat/sdk/pdf/javascript/AcroJSGuide.pdf">pdf file</a>) and Reference (<a href="http://partners.adobe.com/public/developer/en/acrobat/sdk/pdf/javascript/AcroJS.pdf">pdf file</a>),</li><li>Some basic knowledge of Java servlets,</li><li>Some knowledge of the <a href="http://www.lowagie.com/iText">iText PDF library</a> or atleast some enthusiasm to learn it.<br /></li></ul><span style="font-size:130%;"><span style="font-weight: bold;">Pr</span></span><span style="font-size:130%;"><span style="font-weight: bold;">é</span></span><span style="font-size:130%;"><span style="font-weight: bold;">cis</span></span><br /><br />I will demonstrate how to generate a PDF document with the iText PDF library. The document will have embedded Acrobat Javascript in it. Using the Acrobat Javascript commands I will ensure that the PDF document will be printed (to the default printer) when it is opened, followed by an attempt to close the document (which may not succeed when the document is opened inside a browser using the Acrobat Reader plugin or BHO). The PDF with the embedded Acrobat Javascript is served by a Java servlet which allows for the solution to be demonstrated over the internet.<br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">Source Code</span></span><br /><br />The WAR (Web ARchive) file containing the servlet and the iText library can be <a href="http://clip2net.com/page/m6825/138378">downloaded here</a>(You can mail me if the download fails). You could straightaway deploy it on Apache Tomcat or any other servlet container or even a J2EE application server.<br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">What's going on?</span></span><br /><br />The important stuff is being done here:<br /><br /><blockquote><span style="font-size:85%;">/*<br />The output stream of the servlet to which the PDF document is sent.<br />*/<br />ServletOutputStream out = response.getOutputStream();<br /><br />/*<br />Create an iText document - that's a PDF document that we're creating.<br />*/<br />Document document = new Document();<br /><br />/*<br />Create a ByteArrayOutputStream to which the document will be written (the document will NOT be created on as a disk file at the server - use FileOutputStream for that.<br />*/<br />ByteArrayOutputStream baos = new ByteArrayOutputStream();<br /><br />try {<br /><br />/*<br />We get an instance of Pdfwriter. The instance is "listening" to the document object, and is "tied" to the byte array output stream. This means - whenever we add elements to the document the writer object picks it up and transfers it to the output stream.<br />*/<br />PdfWriter writer = PdfWriter.getInstance(document, baos);<br /><br />/*<br />I'm setting the viewer preferences so that the user is not able to see the menubar or scrollbar inside the browser when this file is opened using the Acrobat Reader PDF plugin. This could be treated as a "security measure" for preventing users from saving the file or printing the file once again. Be careful - it's a viewer preference and not a security provision. It can be reverted by the user because it's only an indication to the Reader plugin on how the document is to be presented when it is initially loaded.<br />*/<br /> writer.setViewerPreferences( PdfWriter.HideMenubar | PdfWriter.HideToolbar | PdfWriter.HideWindowUI );<br /><br />/*<br />We have to open the document for writing information after the header and meta-information is added. Which means that we have to "prepare" the document before we are have to write the user-visible information.<br />*/<br />document.open();<br /><br />/*<br />We now add a document level Javascript action so that the entire action is executed when the document is opened. To see what other options are available, you will have to go through the Acrobat Javascript <a href="http://partners.adobe.com/public/developer/en/acrobat/sdk/pdf/javascript/AcroJS.pdf">Reference</a> and <a href="http://partners.adobe.com/public/developer/en/acrobat/sdk/pdf/javascript/AcroJSGuide.pdf">Guide</a> (links are same as above).<br />The necessary information can be found in the Doc object provided by the Acrobat Javascript model. The Doc object can be referenced usually by using the "this" object.<br />*/<br />writer.addJavaScript(<br /> "this.print({bUI: false,bSilent: false,bShrinkToFit: true});" +<br /> "\r\n" +<br /> "this.closeDoc();"<br /> );<br /><br />/*<br />We add some dummy statement to be printed.<br />I hate to print a blank document, but I dont waste paper.<br />So, if you are environment conscious, please enter whitespaces instead.<br />Do not (God forbid), remove the line of code below to save on paper. LOL.<br />*/<br />document.add(new Chunk("Silent Auto Print"));<br /><br />/*<br />You have to close the document when you're done with it.<br />*/<br />document.close();<br />}<br />catch (DocumentException e)<br />{<br />e.printStackTrace();<br />}<br /><br />/*<br />I'm setting the content type of the response so that the browser will recognize that it is going to receive a PDF file. However, do not be too confident about this.<br />Some browsers - especially IE and Opera are known to do "content-sniffing" to determine what is to be done with a server's response. And that could change the equation drastically.<br />*/<br />response.setContentType("application/pdf");<br /><br />/*<br />Some browsers are known to flip and throw up when they dont know how much data is going to be received by them. So it is wise to set the content length header before sending data to the browser.<br />*/<br />response.setContentLength(baos.size());<br /><br />/*<br />We wrote the document to a ByteArrayOutputStream. Now flush that stream to the servlet's response object.<br />*/<br />baos.writeTo(out);<br /><br />/*<br />Flush the servlet's response object so that the servlet responds to the browser's request.<br />*/<br />out.flush();</span> </blockquote><br /><br /><span style="font-weight: bold;font-size:130%;" >A Trial Run</span><br /><br />You could go to <a href="http://vineetreynolds.users.mcs2.netarray.com/SilentPrintDemo/index.html">this demonstration page</a> and see how it works. Be sure to try this out in different environments - with and without Acrobat Reader browser plugin installed, with and without SP2 installed on Windows XP, different browsers (especially Firefox and Opera), and even when the user is able to save the file and then open it. You'll learn quite a lot on why I chose to write the servlet this way and not any other way. Consistency matters a lot when it comes to the internet.<br /><br /><div class="techtags">Tech Tags: <a href="http://technorati.com/tag/Adobe" rel="tag" class="techtag">Adobe</a> <a href="http://technorati.com/tag/Acrobat" rel="tag" class="techtag">Acrobat</a> <a href="http://technorati.com/tag/JavaScript" rel="tag" class="techtag">JavaScript</a> <a href="http://technorati.com/tag/iText" rel="tag" class="techtag">iText</a> <a href="http://technorati.com/tag/PDF" rel="tag" class="techtag">PDF</a> </div><br /></span>Anonymoushttp://www.blogger.com/profile/13688757724895249188noreply@blogger.com15tag:blogger.com,1999:blog-10189396.post-1136649823393239642006-01-07T20:17:00.000+05:302008-01-29T00:31:30.192+05:30Root finding algorithms and their "near similarity" to search algorithmsJust don't know how to get started on this.<br />Two vast topics and I cant pinpoint the origin of this idea of mine.<br /><br />This idea sprang up sometime in the 3rd semester of my CS degree during the Applied Mathematics course. No point giving credit to the course because it never exercised my mind.<br />Back onto the spicy stuff anyway.<br /><span class="fullpost"><br />The Applied Mathematics course had a section on <a style="font-weight: bold;" href="http://en.wikipedia.org/wiki/Category:Root-finding_algorithms">root-finding algorithms</a> for <a style="font-weight: bold;" href="http://en.wikipedia.org/wiki/Root-finding_algorithm#Finding_roots_of_polynomials">polynomial equations</a>. I noticed a distinctive similarity between the <a style="font-weight: bold;" href="http://en.wikipedia.org/wiki/Bisection_method">bisection method</a> to find the root of a polynomial function f(x), and the <a style="font-weight: bold;" href="http://en.wikipedia.org/wiki/Binary_search">binary search algorithm</a> to find the position of a key.<br />For starters, especially those who are not from the CS/Math stream, this might be a bit confusing so I'll provide extensive details as far as possible.<br /><br />The bisection method is the simplest root finding algorithm. One can find the root of a function f(x)=0 by trying to approximate the range of values of the function in which there is a better probability of finding the root of the function. Read on if you still didn't understand.<br />Basically any function f(x)=0 can be treated as a series of values that vary with the variable (or parameter) x. So, if you "feed" in different values for x, you should get different values for f(x). The root of the function f(x) is that value of x at which f(x) equals 0. You normally don't have a lot of roots for a function f(x) - the number of roots for f(x) depends solely on the degree of the function f(x).<br />To demonstrate the similarity between the concept of root finding of a mathematical function f(x), and searching for key in a stream of numbers (a stream or sequence of numbers to which binary search or any other search algorithm can be applied), I make one important assumption :<br /><br />Any stream of numbers [0, 1, 5, 7 , 14, 76, 196, 256, 983, 1005,.......] can be represented by an imaginary function f(x) - imaginary as in virtual/hallucination, not (-1)^(1/2).<br />OR<br />Any function f(x) will have a corresponding stream of "data" that depends on what values of x have been applied to the function to produce the stream.<br /><br />We'll put this important stumbling block behind us.<br />Now for the correlation between the word "root" of a function f(x)=0, and the word "key" of the binary search algorithm.<br /><br />The "root" of the function f(x)=0, is that value of x that will ensure f(x) will produce a value of 0.<br />The "key" of the binary search algorithm is a possible value among the series of values produced by application of differing values of x to f(x). If the key element has been found in the stream of values, then our search is successful; if it hasn't been found, then the search is simply unsuccessful.<br />Finding the key in a stream is the same as finding the root of the function f(x) = key, x = 1,2,3,4,5........ :x denotes the position of an element in the stream [ if f(x) has the values 12, 45 , 65, 54 , 43, 78, then f(1) = 12, f(2) = 45, f(3) = 65 , f(4) = 54, f(5) = 43 , and so on].<br />If we find the key among the stream of values then we can find out the corresponding position in the stream, which is usually what most CS search algorithms have to do.<br /><br /><span style="font-weight: bold;">Similarity between the bisection method and the binary search algorithm</span><br /><br />In both these algorithms, we divide the interval of values in half. For the binary search algorithm, the stream of values must be sorted so that it satisfies the requirement for the bisection method that can operate only on a continuous function f(x) !!<br /><br />The binary search algorithm is definitely not the fastest as we know. But it definitely has predictable behavior as we all know - O(log n).<br /><br />The question is now of beating this - application of algorithms that can converge on a "key" or the "root of the corresponding function f(x)" faster than binary search or bisection method can.<br />There are better root-finding methods than bisection method - <a href="http://en.wikipedia.org/wiki/Newton%27s_method">Newton's method</a>, <a href="http://en.wikipedia.org/wiki/Secant_method">Secant method</a>, <a href="http://en.wikipedia.org/wiki/False_position_method">false position</a>, <a href="http://en.wikipedia.org/wiki/Linear_interpolation">linear interpolation</a>(secant method again), <a href="http://en.wikipedia.org/wiki/Polynomial_interpolation">polynomial interpolation</a>(Muller's method), <a href="http://en.wikipedia.org/wiki/Inverse_quadratic_interpolation">inverse quadratic interpolation</a>, and <a href="http://en.wikipedia.org/wiki/Brent%27s_method">Brent's method</a>. Phew !!!!!!<br />Of course not all can be applied for searching, and not all can have predictable O(n) behaviors.<br />More research is required in this area. And certainly in designing the data structures/ databases that are optimized for such types of searches; certainly in determining if certain functions can be readily applied to existing data structures / databases.<br /><a href="http://discuss.techinterview.org/default.asp?interview.11.265901.26">Some theoretical problems too exist</a> and they've been thankfully pointed out by Jim Lyon and Roman Werpachowski. At first glance, these could be ironed out by approximation and tweaking of the algorithms. But it still requires research !! And so I have to end my lecture here.<br /><br /><a href="http://discuss.techinterview.org/default.asp?interview.11.265901.26">A discussion of this algorithmic technique can be found at JoS</a>.<br /></span>Anonymoushttp://www.blogger.com/profile/13688757724895249188noreply@blogger.com0tag:blogger.com,1999:blog-10189396.post-1134398516522430822005-12-12T18:53:00.000+05:302008-01-28T04:06:38.917+05:30Silent Print a PDF !! Print PDF programmatically....<div style="text-align: justify;"><span style="font-weight: bold;"> Update</span>: Please do not forget to check the other PDF and print related links in the sidebar<br /><br /><br />If you have come to this page after a Google search on the following terms - "<span style="font-weight: bold;">print PDF in a programmatic method</span>", "<span style="font-weight: bold;">silent print</span>", "<span style="font-weight: bold;">automate PDF print</span>" then it is probable that you have come to the right place. This would be true especially if you want a cheap / free / open source solution to print PDF automatically.<br /><span class="fullpost"><br />And if you just want the answer to question on "How to prevent users from saving a PDF document ?", then just go into the <a href="http://www.adobeforums.com/cgi-bin/webx?50@325.xMZzfupBEXe.5@.3bbb311e">Adobe Acrobat forums</a> where the issue has been highlighted as a "most frequently asked question"<a href="http://www.adobeforums.com/cgi-bin/webx?50@325.xMZzfupBEXe.5@.3bbb311e"><span style="font-weight: bold;"></span></a>. There is another interesting and well-explained article available <a href="http://www.adobeforums.com/cgi-bin/webx?13@325.xMZzfupBEXe.7@.3bbac656/0"><span style="font-weight: bold;"></span></a>on <a href="http://www.adobeforums.com/cgi-bin/webx?13@325.xMZzfupBEXe.7@.3bbac656/0">why it is futile to prevent website viewers from saving your "secure" PDF files</a>. And good luck, if you plan to leave already without reading the rest of the article.<br /><br /><br />First of all, take a deep breath of air; you will be going through quite a long ride now.<br /><br /><br />Let's go through the basics first.<br /><br />A printer is a device / resource in the context of operating systems. So all printing is done at the behest of the operating system. For a layman, this would mean - the user has control over what to print and what not to print, how to print and whether the print commands can be archived for printing the same document later on. You might ask - how is it possible to store the print commands ? Well, it is possible to have software / print servers that will store such printing instructions. This is usually the case in my friend's company - the print server software stores all submitted documents for a week, after which they are discarded. Point to be noted : to print something the printer will need printer-level instructions, and those instructions can be stored in printer memory to be reused later.<br />Coming back to the point, silent printing or for that matter even user guided printing requires code to exercise control over the Operating System. So if you want a silent print without any hassles, your success in achieving it will depend on how much control you can exercise over the Operating System from a given environment - "trusted" desktop application based printing, website based printing, "signed" applet based printing...........................................<br /><br />Now on to the gory details of PDF.<br /><br />PDF is a Adobe file format that is a tempered down version of Adobe's Postscript format [technically Postscript is a programming as is any other computer programming language].<br />So if you want to print a PDF file [with or without user interaction], you will have to convert the information in the PDF file to Postscript. This will enable the printer Postscript driver to issue printer specific commands [note the word "commands", this is one reminder that Postscript is a programming language] that produce the required output accurately.<br />It is a different issue for printers that come without a Postscript driver. Certain printers especially that of HP might come with <a href="http://h20000.www2.hp.com/bizsupport/TechSupport/Document.jsp?objectID=bpl04568">PCL [ Printer Command Language ]</a> drivers instead. And there comes the additional step of converting the Postscript data to data understood by PCL. This implies that to print a PDF, you'll have to write code to be capable of converting PDF/Postscript to the native format understood by the printer.<br />One such product capable of doing that is the free Adobe Acrobat Reader. This well-known product does have it's limitations however. Command line options to print the PDF are undocumented / unsupported by Adobe. The Acrobat Reader process is known to start, print and continue running even after a silent print via command line; a bug that's not yet fixed by Adobe. Which means - you should expect to see a blank Acrobat Reader window after the "silent print". There are <a href="http://aspalliance.com/514">"beat around the bush"</a> methods to attain certain amount of success using the commandline options - not for those who want "<span style="font-weight: bold;">da perfect solution</span>".<br /><a href="http://partners.adobe.com/public/developer/en/acrobat/sdk/pdf/iac/IACReference.pdf">Inter Application Communication </a>(<span style="font-weight: bold;">IAC PDF reference file available at <a href="http://partners.adobe.com/public/developer/en/acrobat/sdk/pdf/iac/IACReference.pdf">link</a></span>) with the free Acrobat Reader cannot be done via OLE automation give the fact that Acrobat Reader is not a OLE server; you can get some luck only with Acrobat Standard or Pro. Only DDE messages can help a programmer write an application to achieve this. <a href="http://www.codeproject.com/cpp/ReaderWrapper.asp">DDE will have restrictions</a> that are not faced by an OLE Server. [If you don't know the difference then you musn't be doing this anyway].<br /><br />Commercial libraries could alleviate this problem, but they might have to installed at the client systems - licenses for such usage are known to be highly priced [Consider this option in an enterprise application]. Such libraries are available for both .Net and Java. Availability of ports to other languages / frameworks will depend on the demand for the ports.<br /><br />There are other solutions as well - the Acrobat JavaBean to view and print a PDF file. You can keep away from this, given the fact that it is very obsolete and is known to produce smudgy previews and printouts. Very buggy and should not be used unless your customers don't want printouts. In short, <span style="font-weight: bold;">keep away</span> even if this <a href="http://today.java.net/pub/a/today/2005/10/20/accessing-pdf-with-acrobat-viewer-javabean.html">"recent" article"</a> seems to help you.<br /><br />Rumours have it that Sun Microsystems has an in-house library that produces high quality output. The reason for it's unavailability is however unknown. Seems like there are some licensing issues there, which might also be one of the reasons why the org.jdesktop.jdnc.incubator.rbair packages disappeared all of a sudden. If you got excited by having a look at the <a href="http://java.sun.com/j2se/1.4.2/docs/guide/jps/">Java Print Service</a> (which was initially offered to solve all printing problems!! ) and discovered that there is a PDF Docflavor, then it is time to cool down; take a peek at this <a style="font-weight: bold;" href="http://www-128.ibm.com/developerworks/java/library/j-mer0322/">link</a>. I'd also quote the most important part of the page (right at the end)........<br /><div style="text-align: justify;"><blockquote><span style="font-size:85%;"><br />"Just because the PDF DocFlavor exists doesn't mean you can use it to print a PDF file. When you lookup the PrintService for the PDF flavor, it will report unsupported flavor. That means there is no print service for the flavor. Sun doesn't provide one for PDF files. To the best of my knowledge, nobody else makes one available either. Until such a time as someone does, you can't print PDF files using the new Print Service API."<br /><br /></span></blockquote>There are open source solutions as well that might get the job done, but I wouldn't recommend any, given the fact that I consider none of them are mature enough to be used in commercial projects with a heavy stake on print output quality. For some exploratory programming you could try <a href="http://www.jpedal.org/gpl.html">JPedal</a> and <a href="http://www.pdfbox.org/">PDFBox</a>.<br /></div><br />You can otherwise think of buying commercial libraries that will rasterize [convert the PDF data into a bitmap] and print the PDF files. And if you want to avoid all this, you'll need to write your own code to rasterize and print the PDF file - the time penalty for doing such a thing is huge [Commercial rasterization libraries sell for $500 and up for developer licenses, so duplicating that effort will take that many man hours]. Links for exploratory activity include: <a href="http://www.tallcomponents.com/">TallComponents</a> and <a href="http://www.icesoft.com/">ICEsoft</a>. The list is not comprehensive though.<br /><br />I have thus outlined the methods to print a PDF file via a local system application.<br /><br />Now onto that "silly, but not mediocre" request of silent print of an Internet based PDF file via the browser.<br />First of all, the browser's job is to display HTML and probably print a HTML page and nothing else. If you want it to print a PDF file, you'll need a browser helper object [BHO]. Try coding BHOs for all browsers and you'll know you're asking for manna.<br />You could rely on the Adobe Acrobat IE BHO/plugin, but it's not foolproof. If you want to know why, then you ought to read even more carefully now - there are umpteen ways/hacks/methods to disrupt that method. No known document exists, which can pinpoint the Internet Explorer and Acrobat BHO settings that will disrupt the plugin's functionality. Simply turning the plugin off, and switching it back on, by using the Acrobat Reader preferences menu can disrupt that functionality !! So much for relying on Acrobat Reader to be a carefully engineered application.<br /><br />There is however an easier but <span style="font-style: italic;">hack 'n slash</span> way to do it; use a document level JavaScript print action [ for more information have a look at the Adobe Acrobat JavaScript <a href="http://partners.adobe.com/public/developer/en/acrobat/sdk/pdf/javascript/AcroJSGuide.pdf">Guide</a>(pdf) and <a href="http://partners.adobe.com/public/developer/en/acrobat/sdk/pdf/javascript/AcroJS.pdf">Reference</a>(pdf) ]. The print action is to execute on any valid action - usually a page action. But remember, JavaScript with Acrobat Reader can be disabled by the user. And it is impossible to close Acrobat Reader [not the opened document] after the print is finished - you'll need to "deliberately crash" Reader after the print is done. And if the PDF file opens in a browser window [ on account of the Acrobat Reader BHO], then you can forget about trying to close the PDF document in a programmatic manner. One of the <a href="http://www.lowagie.com/iText/">iText</a> <a href="http://itext.ugent.be/library/com/lowagie/examples/general/webapp/SilentPrintServlet.java">examples</a> shows how a servlet could be written to achieve this. Try a demo <a href="http://blowagie.users.mcs2.netarray.com/servlet/silentprint">here</a>! and make sure you run it in different browsers under different settings (for example : Win XP with SP 2 and without SP2), to understand the varying functionality that it provides. <span style="font-weight: bold;">Golden rule</span> to be respected in any software : Never make it behave inconsistently; your users could have trouble describing their problems.<br /><br />You are lucky if you want an IE only solution with certain restrictions - hop onto ActiveX programming using MeadCo's <a href="http://www.meadroid.com/scriptx/index.asp">ScriptX</a>. As again, this solution depends on how stable Internet Explorer will turn out to be. Windows XP SP2 will definitely throw up the security message bar regarding the webpage's attempt to execute code (remember that webpages were to display HTML, not run some virus proof of concept).<br /><br />Some people also like a "PDF Preview" in the browser. My answer would be - "that's not the job of the browser"; write something to help the browser do that - an ActiveX plugin, Browser Helper Object [BHO] or a Java applet is what you want. <a href="http://www.planetpdf.com/developer/article.asp?ContentID=6759">The Adobe Acrobat IE/Mozilla BHO might do the job</a> for you if the stars were in the right alignment at the time of your birth; please dont ask me to support the article present at the link. And yes, you can print via the ActiveX plugin / Java applet; but it's not easy given the fact that brilliance always has a limit. ActiveX controls / Java applets that do that task come with the "$$" penalty. You should invest time or money to get that done.<br /><br />And stop cribbing if you still havent ;-) or ask your boss to stop ;-). Atleast Adobe has licensed the PDF format so that you can use it (naughty boy, you thought everything was free, eh?). Imagine your silly client's fate if you had to write your proprietary file format to enforce a thinly veiled DRM idea of his. Frankly, I've had enough of the people asking for solutions like - " How can I get the client to print my PDF document without saving it. My budget is 50$ ". The answer is - you don't do it with basic code. You'll need to write a <a href="http://partners.adobe.com/public/developer/acrobat/reader/topic_drm.html">DRM plugin</a> (which will cost your client moolah; remember nothing is free) or use <a href="http://www.adobe.com/products/server/policy/main.html">Adobe LiveCycle Policy Server</a> or buy <a href="http://partners.adobe.com/public/developer/security/index_security_partners.html">security solutions from Adobe's partners</a>, which ever fits into your budget and needs.<br /><br />And on a parting note, "See ya !! Talk to you later !!!! I hope it was a pleasure to be bored by listening to me, as much as the pleasure I felt in boring you ;-) "<br /></span></div><br /><br /><div class="techtags">Tech Tags: <a href="http://technorati.com/tag/Adobe" rel="tag" class="techtag">Adobe</a> <a href="http://technorati.com/tag/Acrobat" rel="tag" class="techtag">Acrobat</a> <a href="http://technorati.com/tag/JavaScript" rel="tag" class="techtag">JavaScript</a> <a href="http://technorati.com/tag/iText" rel="tag" class="techtag">iText</a> <a href="http://technorati.com/tag/PDF" rel="tag" class="techtag">PDF</a> <a href="http://technorati.com/tag/JPedal" rel="tag" class="techtag">JPedal</a> <a href="http://technorati.com/tag/print" rel="tag" class="techtag">print</a> <a href="http://technorati.com/tag/MeadCo" rel="tag" class="techtag">MeadCo</a> <a href="http://technorati.com/tag/ScriptX" rel="tag" class="techtag">ScriptX</a> <a href="http://technorati.com/tag/plugin" rel="tag" class="techtag">plugin</a> <a href="http://technorati.com/tag/browser" rel="tag" class="techtag">browser</a> <a href="http://technorati.com/tag/PDFBox" rel="tag" class="techtag">PDFBox</a> <a href="http://technorati.com/tag/browser+helper+object" rel="tag" class="techtag">browser+helper+object</a> <a href="http://technorati.com/tag/rasterize" rel="tag" class="techtag">rasterize</a> <a href="http://technorati.com/tag/Tall+Components" rel="tag" class="techtag">Tall+Components</a></div>Anonymoushttp://www.blogger.com/profile/13688757724895249188noreply@blogger.com21