Creating a TIF file with a resolution of X ppi from a PDFBox PDPage

Submitted by Jochus on Sun, 25/11/2012 - 22:54 | Posted in: Java
Posted in

In order to have the correct ppi in the TIF file, you need to specify IIOMetadata for the TIF file and pass it to the constructor of the IIOImage.
In the example below, you can see the creation of this metadata in the function: createMetadata()

...
PDDocument document = null;
 
try {
	// Set main options
	int imageType = BufferedImage.TYPE_BYTE_BINARY;
	int resolution = X;
	int maxPage = Integer.MAX_VALUE;
 
	// Create TIFF writer
	ImageWriter writer = null;
	ImageWriteParam writerParams = null;
	try {
		TIFFImageWriterSpi tiffspi = new TIFFImageWriterSpi();
		writer = tiffspi.createWriterInstance();
		writerParams = writer.getDefaultWriteParam();
		writerParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
		writerParams.setCompressionType("CCITT T.6");
		writerParams.setCompressionQuality(1.0f);
	} catch (Exception ex) {
		throw new BusinessException("Could not load the TIFF writer", ex);
	}
 
	// Create metadata for Java IO ImageWriter
	IIOMetadata metadata = createMetadata(writer, writerParams, resolution);
 
	// Load the pdf file
	document = PDDocument.load(file.getFile());
	List<PDPage> pages = (List<PDPage>) document.getDocumentCatalog().getAllPages();
 
	// Loop over the pages
	for (int i = 0; i < pages.size() && i <= maxPage; i++) {
		// Write page to image file
		File outputFile = null;
		ImageOutputStream ios = null;
		try {
			outputFile = new File(file.getFile().getCanonicalPath() + "." + i);
			ios = ImageIO.createImageOutputStream(outputFile);
			writer.setOutput(ios);
			writer.write(null, new IIOImage(pages.get(i).convertToImage(imageType, resolution), null, metadata), writerParams);
		} catch (Exception ex) {
			throw new BusinessException("Could not write the TIFF file", ex);
		} finally {
			ios.close();
		}
 
		// do something with TIF file
	}
} catch (Exception ex) {
	throw new BusinessException("Error while converting PDF to TIFF", ex);
} finally {
	try {
		if (document != null) {
			document.close();
		}
	} catch (Exception ex) {
		log.error("Error while closing PDF document", ex);
	}
}
...
 
// Internal methods
 
private IIOMetadata createMetadata(ImageWriter writer, ImageWriteParam writerParams, int resolution) throws IIOInvalidTreeException {
	// Get default metadata from writer
	ImageTypeSpecifier type = writerParams.getDestinationType();
	IIOMetadata meta = writer.getDefaultImageMetadata(type, writerParams);
 
	// Convert default metadata to TIFF metadata
	TIFFDirectory dir = TIFFDirectory.createFromMetadata(meta);
 
	// Get {X,Y} resolution tags
	BaselineTIFFTagSet base = BaselineTIFFTagSet.getInstance();
	TIFFTag tagXRes = base.getTag(BaselineTIFFTagSet.TAG_X_RESOLUTION);
	TIFFTag tagYRes = base.getTag(BaselineTIFFTagSet.TAG_Y_RESOLUTION);
 
	// Create {X,Y} resolution fields
	TIFFField fieldXRes = new TIFFField(tagXRes, TIFFTag.TIFF_RATIONAL, 1, new long[][] { { resolution, 1 } });
	TIFFField fieldYRes = new TIFFField(tagYRes, TIFFTag.TIFF_RATIONAL, 1, new long[][] { { resolution, 1 } });
 
	// Add {X,Y} resolution fields to TIFFDirectory
	dir.addTIFFField(fieldXRes);
	dir.addTIFFField(fieldYRes);
 
	// Return TIFF metadata so it can be picked up by the IIOImage
	return dir.getAsMetadata();
}

JRebel constantly reloading every class file and every configuration file in our Java project

Submitted by Jochus on Mon, 19/11/2012 - 23:04 | Posted in: Java
Posted in


We are using JRebel at work now for a couple of weeks, and this product is really a timesaver for every Java developer. No need to redeploy/restart your application server: just code and push refresh in the browser.

But, we sometimes had the issue the whole project was getting reloaded and we only changed 1 line of code in 1 class file. After a bit of research, we found out Eclipse just cleans the whole bin folder. Every class file was recompiled.

The reason why is still unknown. I couldn't figure this out. Anyways, it was really frustrating as the only solution to stop the reloading process, was to restart the application server. And if you have to restart the application server, why would you use JRebel?

The first thing I tried is stopping the "Automatic build" option in Eclipse. Disabling build automatically option does not break JRebel. JRebel depends on the results of the compilation, so if you disable the automatic build you will have to just compile the changed classes yourself, that's it.

But I didn't like that option either, so we found an option in JRebel which is actually a VM argument: -Drebel.check_class_hash=true which will check the checksum before reloading the classes. It may slow down the reloading time from a few milliseconds to some milliseconds extra. But it is still better than the situation when all the project classes have to be reloaded.

To summarize, this is my JRebel configuration in $JBOSS_HOME/bin/run.conf:

# JRebel
JAVA_OPTS="$JAVA_OPTS -javaagent:$JREBEL_HOME/jrebel.jar -Drebel.log=false -Drebel.check_class_hash=true"
JAVA_OPTS="$JAVA_OPTS -D##PRODUCT_NAME##.root=/Users/jochen/Documents/workspace/##PRODUCT_NAME##"

CSS3 spin animation

Submitted by Jochus on Tue, 13/11/2012 - 16:56 | Posted in: Website
Posted in

I just learned this cool CSS3 animation on Devoxx :-)! Hover the Chrome logo!
Not sure it's gonna work on Internet Explorer ... :p ...

 



 

Logging all queries executed on MySQL database

Submitted by Jochus on Mon, 12/11/2012 - 23:23 | Posted in: Database
Posted in


I wanted to debug some SQL queries which are coming from my data access layer (JPA with Hibernate) and which are being send to my MySQL server. The following steps are needed:

  • Create the file /etc/my.cnf (I installed MySQL manually from a .pkg installer, so the file is not there by default - you have to create it manually)
  • Add the following lines:

    [mysqld]
    log=/tmp/mysql-query.log
  • Create the .log file:
    $ sudo touch /tmp/mysql-query.log
  • Allow MySQL daemon to write in file:
    $ sudo chown _mysql /tmp/mysql-query.log
  • Restart MySQL daemon:
    ~ $ cd /usr/local/mysql/support-files/
    /usr/local/mysql/support-files $ sudo ./mysql.server restart

Cleaning the cache of address book in Outlook for Mac 2011 (Global Address List on Microsoft Exchange)

Submitted by Jochus on Sun, 11/11/2012 - 22:43 | Posted in: Mac
Posted in


When connecting from Outlook for Mac 2011 to a Microsoft Exchange server, Outlook caches the Global Address List for a day. Changes made on the Exchange server, are not directly visible in your Outlook.

If you want to force an update, you can follow the steps below:

# Close Outlook
~ $ cd Library/Caches/Outlook/Main\ Identity/1/
~/Library/Caches/Outlook/Main Identity/1 $ rm OABQueryInfo.plist 
# Startup Outlook - the latest version of the address book will be retrieved from the server

Rolling back a transaction in TransactionManagementType.CONTAINER EJB

Submitted by Jochus on Tue, 06/11/2012 - 22:33 | Posted in: Java
Posted in

Rolling back a transaction in a TransactionManagementType.BEAN

First of all, there's a difference with a TransactionManagementType.BEAN EJB. When an EJB is marked with the @TransactionManagement(TransactionManagementType.BEAN) annotation, transaction management is performed by calling the methods in the UserTransaction class.

Example:

@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class FooBarBean implements FooBar {
	@Resource
	private UserTransaction tx;
 
	public void someMethod() throws Exception {
		try {
			  tx.begin();
 
			  // do something 
 
			  tx.commit();
		} catch(Exception ex) {
			  tx.rollback();
                          throws ex;
	        }
        }
...

For every method in which you need a transaction, you have to control the UserTransaction by yourself.

Rolling back a transaction in a TransactionManagementType.CONTAINER

Example:

@Stateless
public class FooBarBean implements FooBar {
	@Resource
	private EJBContext context;
 
	public void someMethod() throws Exception {
		try {
			// do something
		} catch(Exception ex) {
			context.setRollbackOnly();
                        throws ex;
		}
	}
}

The transaction will be automatically started at the start of the method and it will be committed at the end of the method.
The moment when context.setRollbackOnly() is invoked, the transaction will just be marked as rollback only and nothing will be persisted when the method ends and returns.

Upgrading Python to version 2.6 on Ubuntu Intrepid 8.10

Submitted by Jochus on Thu, 25/10/2012 - 21:37 | Posted in: Linux
Posted in


I have an old Ubuntu 8.10 server running at home. Today, I wanted to create a script which needs Python. The latest version of Python in the Intrepid Ubuntu repository is 2.5, but I needed 2.6. Luckily, it's very easy to install 2.6 from source and run it next to the 2.6 version!

  • Download the Python 2.6 sources from http://www.python.org/download/releases/2.6.8/
  • Unzip and execute the following commands
    $ sudo ./configure --prefix=/usr/lib/python/2.6
    $ sudo make
    $ sudo make install
  • You are now able to use Python 2.6 from: /usr/lib/python/2.6/bin/python

Retrieving the number of physical/logical CPU's in Windows + detecting HyperThreading support

Submitted by Jochus on Tue, 23/10/2012 - 22:56 | Posted in: Windows
Posted in


If you want to get the number of physical CPU cores, execute the following command:

for /F "tokens=2 delims==" %C in ('wmic cpu get NumberOfCores /value ^| findstr NumberOfCores') do @echo %C

If you want to get the number of logical CPU processors, execute the following command:

for /F "tokens=2 delims==" %C in ('wmic cpu get NumberOfLogicalProcessors /value ^| findstr NumberOfLogicalProcessors') do @echo %C

If the ratio of the above 2 numbers is 1/2, it means your CPU supports HyperThreading.