Total Pageviews

2016/07/09

[PDFBox] No ImageWriter found for 'tif' format in WebSphere

Problem
As I try to convert PDF to TIF via PDFBox in WebSphere 8, I got the error message during the conversion process:
1
2
[Line:198][org.apache.pdfbox.tools.imageio.ImageIOUtil.writeImage]No ImageWriter found for 'tif' format
[Line:206][org.apache.pdfbox.tools.imageio.ImageIOUtil.writeImage]Supported formats: BMP bmp jpg JPG wbmp jpeg png PNG JPEG WBMP GIF gif 


Lacking of jai-imageio-core jar file in your classpath must get this error message.
But I have add jai-imageio-core dependency in pom.xml.
Snippet of pom.xml looks like:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<!-- for generating tif file -->
<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox-tools</artifactId>
    <version>2.0.0</version>
</dependency>

<dependency>
    <groupId>com.github.jai-imageio</groupId>
    <artifactId>jai-imageio-core</artifactId>
    <version>1.3.1</version>
</dependency>

Therefore, I try to print log to figure out the weird problem:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
 try {
     Enumeration<URL> urls = Thread.currentThread().getContextClassLoader()
             .getResources("META-INF/services/javax.imageio.spi.ImageWriterSpi");
     while (urls.hasMoreElements()) {
         log.info("[convertToTiff] url = " + urls.nextElement().toString());
     }
 
 } catch (IOException e1) {
     e1.printStackTrace();
     throw new RuntimeException(e1);
 }

 The jar file exists in my ear file ! What happened?
1
 [convertToTiff] url = wsjar:file:/usr/IBM/WebSphere/AppServer/profiles/AppSrv03/installedApps/FDCSRA205Node03Cell/yuantalife-ecp-manage.ear/yuantalife-ecp-manage-war-0.1.0-SNAPSHOT.war/WEB-INF/lib/jai-imageio-core-1.3.1.jar!/META-INF/services/javax.imageio.spi.ImageWriterSpi

Here is my source code:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package albert.practice.file;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;

import javax.imageio.ImageIO;

import lombok.extern.slf4j.Slf4j;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.tools.imageio.ImageIOUtil;

@Slf4j
public class PdfFileToTif {

    private final float dpi = 300f;

    public static void main(String[] args) {
        File pdfFile = new File("D:\\dropbox\\Getting Started.pdf");
        String destination = "D:\\dropbox\\";

        PdfFileToTif test = new PdfFileToTif();
        test.checkImageIoJarFile();
        test.convertPdfToTif(pdfFile, destination);
    }

    public void convertPdfToTif(File pdfFile, String destination) {
        if (!isFileExisted(pdfFile)) {
            throw new RuntimeException("File not found ! (" + pdfFile.getAbsolutePath() + ")");
        }

        String pdfFileName = pdfFile.getName();

        try {
            // load PDF document
            PDDocument document = PDDocument.load(pdfFile);

            // create PDF renderer
            PDFRenderer renderer = new PDFRenderer(document);

            // go through each page of PDF, and generate TIF for each PDF page.
            for (int i = 0; i < document.getNumberOfPages(); i++) {
                // Returns the given page as an RGB image with 300 DPI.
                BufferedImage image = renderer.renderImageWithDPI(i, dpi, ImageType.BINARY);

                // Assign the file name of TIF
                String fileName = pdfFileName + "_" + String.format("%02d", i + 1);
                log.debug("Generating  " + fileName + ".tif to " + destination);

                // Writes a buffered image to a file using the given image format.
                ImageIOUtil.writeImage(image, destination + fileName + ".tif", Math.round(dpi));
                image.flush();
            }
            log.debug("PDF to TIF conversion well done!");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 判斷檔案是否存在
     * 
     * @param file
     * @return true - 檔案存在; false - 檔案不存在
     */
    private Boolean isFileExisted(File file) {
        Boolean isExisted = Boolean.FALSE;
        isExisted = (file.exists() && (!file.isDirectory()));
        return isExisted;
    }

    private void checkImageIoJarFile() {
        try {
            Enumeration<URL> urls = Thread.currentThread().getContextClassLoader()
                    .getResources("META-INF/services/javax.imageio.spi.ImageWriterSpi");
            while (urls.hasMoreElements()) {
                log.info("[convertToTiff] urls = " + urls.nextElement().toString());
            }

        } catch (IOException e1) {
            e1.printStackTrace();
            throw new RuntimeException(e1);
        }
    }
}


How-to
The root cause is not so clear. It may results from WebSphere's classloading problem.
Hence, I find an API to scans for plug-ins on the application class path, loads their service provider classes, and registers a service provider instance for each one found with the IIORegistry. This strange problem had been resolved as I add ImageIO.scanForPlugins();

Here is my updated source code (Line46):
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package albert.practice.file;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;

import javax.imageio.ImageIO;

import lombok.extern.slf4j.Slf4j;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.tools.imageio.ImageIOUtil;

@Slf4j
public class PdfFileToTif {

    private final float dpi = 300f;

    public static void main(String[] args) {
        File pdfFile = new File("D:\\dropbox\\Getting Started.pdf");
        String destination = "D:\\dropbox\\";

        PdfFileToTif test = new PdfFileToTif();
        test.checkImageIoJarFile();
        test.convertPdfToTif(pdfFile, destination);
    }

    public void convertPdfToTif(File pdfFile, String destination) {
        if (!isFileExisted(pdfFile)) {
            throw new RuntimeException("File not found ! (" + pdfFile.getAbsolutePath() + ")");
        }

        String pdfFileName = pdfFile.getName();

        try {
            // load PDF document
            PDDocument document = PDDocument.load(pdfFile);

            // Scans for plug-ins on the application class path, loads their service provider
            // classes, and registers a service provider instance for each one found with the
            // IIORegistry.
            ImageIO.scanForPlugins();

            // create PDF renderer
            PDFRenderer renderer = new PDFRenderer(document);

            // go through each page of PDF, and generate TIF for each PDF page.
            for (int i = 0; i < document.getNumberOfPages(); i++) {
                // Returns the given page as an RGB image with 300 DPI.
                BufferedImage image = renderer.renderImageWithDPI(i, dpi, ImageType.BINARY);

                // Assign the file name of TIF
                String fileName = pdfFileName + "_" + String.format("%02d", i + 1);
                log.debug("Generating  " + fileName + ".tif to " + destination);

                // Writes a buffered image to a file using the given image format.
                ImageIOUtil.writeImage(image, destination + fileName + ".tif", Math.round(dpi));
                image.flush();
            }
            log.debug("PDF to TIF conversion well done!");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 判斷檔案是否存在
     * 
     * @param file
     * @return true - 檔案存在; false - 檔案不存在
     */
    private Boolean isFileExisted(File file) {
        Boolean isExisted = Boolean.FALSE;
        isExisted = (file.exists() && (!file.isDirectory()));
        return isExisted;
    }

    private void checkImageIoJarFile() {
        try {
            Enumeration<URL> urls = Thread.currentThread().getContextClassLoader()
                    .getResources("META-INF/services/javax.imageio.spi.ImageWriterSpi");
            while (urls.hasMoreElements()) {
                log.info("[convertToTiff] urls = " + urls.nextElement().toString());
            }

        } catch (IOException e1) {
            e1.printStackTrace();
            throw new RuntimeException(e1);
        }
    }
}




Reference 
[1] http://stackoverflow.com/questions/17178591/how-to-add-tiff-imagereader-to-those-registered-in-grails

2016/07/08

[JavaMail] How to send email via Microsoft Exchange Server?

Problem
I am using JavaMail to write program to send email via Microsoft Exchange Server. How to do it?

How-to
The sample code looks like:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
package albert.practice.mail;

import java.io.File;
import java.util.Properties;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

import lombok.extern.slf4j.Slf4j;

import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;

import albert.practice.mail.params.EmailParams;

@Slf4j
public class ExchangeServerMailTest {

    public static void main(String[] args) {
        // set email parameters
        EmailParams params = new EmailParams();
        params.setReceiverEmail("email address");
        params.setSubject("測試一下");
        params.setContent("測試測試測試測試");

        // call sendMail API
        new ExchangeServerMailTest().sendMail(params);
    }

    public void sendMail(EmailParams params) {
        JavaMailSenderImpl sender = getJavaMailSender();
        MimeMessage message = sender.createMimeMessage();

        try {
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setTo(params.getReceiverEmail());
            helper.setFrom("email address");
            helper.setSubject(params.getSubject());
            helper.setText(params.getContent(), false);

            // set attachment
            FileSystemResource attachment = new FileSystemResource(new File(
                    "D:\\dropbox\\退匯明細表.pdf"));
            helper.addAttachment("退匯明細表.pdf", attachment);
        } catch (MessagingException e) {
            throw new RuntimeException(e);
        }
        sender.send(message);

        log.debug("mail sent..");
    }

    private JavaMailSenderImpl getJavaMailSender() {
        Properties props = new Properties();
        props.put("mail.smtp.auth", true);
        props.put("mail.smtp.ssl.trust", "*");

        // mail server configuration
        String host = "your smtp";
        int port = 25;
        String userName = "your user name";
        String password = "your password";

        JavaMailSenderImpl sender = new JavaMailSenderImpl();
        sender.setJavaMailProperties(props);
        sender.setHost(host);
        sender.setPort(port);
        sender.setUsername(userName);
        sender.setPassword(password);
        sender.setDefaultEncoding("UTF-8");

        return sender;
    }

}




2016/07/07

[JavaMail] javax.mail.MessagingException: Could not convert socket to TLS

Problem
I am using JavaMail set send email via Microsoft Exchange Server.
When I run this program, it show this error message:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
Exception in thread "main" org.springframework.mail.MailSendException: Mail server connection failed; nested exception is javax.mail.MessagingException: Could not convert socket to TLS;
  nested exception is:
 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target. Failed messages: javax.mail.MessagingException: Could not convert socket to TLS;
  nested exception is:
 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; message exception details (1) are:
Failed message 1:
javax.mail.MessagingException: Could not convert socket to TLS;
  nested exception is:
 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
 at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1907)
 at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:666)
 at javax.mail.Service.connect(Service.java:295)
 at org.springframework.mail.javamail.JavaMailSenderImpl.connectTransport(JavaMailSenderImpl.java:501)
 at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:421)
 at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:345)
 at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:340)
 at albert.practice.mail.ExchangeServerMailTest.sendMail(ExchangeServerMailTest.java:49)
 at albert.practice.mail.ExchangeServerMailTest.main(ExchangeServerMailTest.java:28)

The code snippet looks like:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
   private JavaMailSenderImpl getJavaMailSender() {
        Properties props = new Properties();
        props.put("mail.smtp.auth", true);

        // mail server configuration
        String host = "your smtp";
        int port = 25;
        String userName = "your user name";
        String password = "your password";

        JavaMailSenderImpl sender = new JavaMailSenderImpl();
        sender.setJavaMailProperties(props);
        sender.setHost(host);
        sender.setPort(port);
        sender.setUsername(userName);
        sender.setPassword(password);
        sender.setDefaultEncoding("UTF-8");

        return sender;
    } 



How-To
You need to set mail.smtp.ssl.trust in your JavaMail properties.
If set, and a socket factory hasn't been specified, enables use of a MailSSLSocketFactory. 
If set to "*", all hosts are trusted. 
If set to a whitespace separated list of hosts, those hosts are trusted. Otherwise, trust depends on the certificate the server presents.


The updated code snippet looks like:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    private JavaMailSenderImpl getJavaMailSender() {
        Properties props = new Properties();
        props.put("mail.smtp.auth", true);
        // Fix Excpetion: Mail server connection failed; nested exception is
        // javax.mail.MessagingException: Could not convert socket to TLS
        // If set, and a socket factory hasn't been specified, enables use of a
        // MailSSLSocketFactory. If set to "*", all hosts are trusted. If set to a whitespace
        // separated list of hosts, those hosts are trusted. Otherwise, trust depends on the
        // certificate the server presents.
        props.put("mail.smtp.ssl.trust", "*");

        // mail server configuration
        String host = "your smtp";
        int port = 25;
        String userName = "your user name";
        String password = "your password";

        JavaMailSenderImpl sender = new JavaMailSenderImpl();
        sender.setJavaMailProperties(props);
        sender.setHost(host);
        sender.setPort(port);
        sender.setUsername(userName);
        sender.setPassword(password);
        sender.setDefaultEncoding("UTF-8");

        return sender;
    } 


Reference
[1] https://javamail.java.net/nonav/docs/api/com/sun/mail/smtp/package-summary.html

2016/07/06

[WebSphere] How to Configure Shared Library in WAS?

Problem
How do I configure shared library in WAS?

Solution
Go to Environment -> Shared Libraries   
1.    Create your own Shared Library. Add the classpath pointing to your JAR files.


2.    Apply and save this configuration.


Go to Servers -> Application Servers -> Select the server-> Java and Process Management -> ClassLoader.
4.    Click on that class loader.


5.    Click on the Shared Library References


6.    Click on Add.


7.    Add your shared library.




8.    Save and restart Websphere Servers.


Reference
[1] http://www-01.ibm.com/support/docview.wss?uid=swg27023549&aid=1

2016/07/05

[WebSphere] How to Enable Classloading log in WAS?

Problem
How do I know the class loading list which load by WAS?

Solution

  • Step1. Log into WAS administration console
  • Step2. Go to application server > server_name > Java and Process Management > Process definition > Java Virtual Machine, check the verbose classloading option
  • Step3. Save your configuration and restart WAS
  • Step4. You will find the classloading informations in the native_stderr.log, which located in /profiles//logs/ directory. ex. /usr/IBM/WebSphere/AppServer/profiles/AppSrv01/logs/server1

Reference

[PDFBox] No ImageWriter found for 'tif' format

Problem
I try to convert PDF to TIF file via PDFBox, but as I get error message in the conversion process:
1
2
3
4
四月 28, 2016 3:06:38 下午 org.apache.pdfbox.tools.imageio.ImageIOUtil writeImage
SEVERE: No ImageWriter found for 'tif' format
四月 28, 2016 3:06:38 下午 org.apache.pdfbox.tools.imageio.ImageIOUtil writeImage
SEVERE: Supported formats: BMP bmp jpg JPG wbmp jpeg png JPEG PNG WBMP GIF gif 

My source code looks like:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package albert.practice.file;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import lombok.extern.slf4j.Slf4j;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.tools.imageio.ImageIOUtil;

@Slf4j
public class PdfFileToTif {

    private final float dpi = 300f;

    public static void main(String[] args) {
        File pdfFile = new File("D:\\dropbox\\Getting Started.pdf");
        String destination = "D:\\dropbox\\";

        PdfFileToTif test = new PdfFileToTif();
        test.convertPdfToTif(pdfFile, destination);
    }

    public void convertPdfToTif(File pdfFile, String destination) {
        if (!isFileExisted(pdfFile)) {
            throw new RuntimeException("File not found ! (" + pdfFile.getAbsolutePath() + ")");
        }

        String pdfFileName = pdfFile.getName();

        try {
            // load PDF document
            PDDocument document = PDDocument.load(pdfFile);

            // create PDF renderer
            PDFRenderer renderer = new PDFRenderer(document);

            // go through each page of PDF, and generate TIF for each PDF page.
            for (int i = 0; i < document.getNumberOfPages(); i++) {
                // Returns the given page as an RGB image with 300 DPI.
                BufferedImage image = renderer.renderImageWithDPI(i, dpi, ImageType.BINARY);

                // Assign the file name of TIF
                String fileName = pdfFileName + "_" + String.format("%02d", i + 1);
                log.debug("Generating  " + fileName + ".tif to " + destination);

                // Writes a buffered image to a file using the given image format.
                ImageIOUtil.writeImage(image, destination + fileName + ".tif", Math.round(dpi));
                image.flush();
            }
            log.debug("PDF to TIF conversion well done!");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 判斷檔案是否存在
     * 
     * @param file
     * @return true - 檔案存在; false - 檔案不存在
     */
    private Boolean isFileExisted(File file) {
        Boolean isExisted = Boolean.FALSE;
        isExisted = (file.exists() && (!file.isDirectory()));
        return isExisted;
    }

}

pom.xml snippet looks like:
1
2
3
4
5
6
<!-- for generating tif file -->
  <dependency>
      <groupId>org.apache.pdfbox</groupId>
      <artifactId>pdfbox-tools</artifactId>
      <version>2.0.0</version>
  </dependency>


This error message prints from ImageIOUtil:
https://github.com/apache/pdfbox/blob/04292e421e9531616aa2856b908fbdb05b381af7/tools/src/main/java/org/apache/pdfbox/tools/imageio/ImageIOUtil.java#L198

According to the JavaDoc in writeImage method...
Writes a buffered image to a file using the given image format. Compression is fixed for PNG, GIF, BMP and WBMP, dependent of the quality parameter for JPG, and dependent of bit count for TIFF (a bitonal image will be compressed with CCITT G4, a color image with LZW). Creating a TIFF image is only supported if the jai_imageio library is in the class path.
https://github.com/apache/pdfbox/blob/04292e421e9531616aa2856b908fbdb05b381af7/tools/src/main/java/org/apache/pdfbox/tools/imageio/ImageIOUtil.java#L150-L155


How-to
This error message results from jai_imageio library is not in my class path 
Therefore, add jai-imageio-core into dependency will resolve this problem
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<!-- for generating tif file -->
  <dependency>
      <groupId>org.apache.pdfbox</groupId>
      <artifactId>pdfbox-tools</artifactId>
      <version>2.0.0</version>
  </dependency>
  
  <dependency>
      <groupId>com.github.jai-imageio</groupId>
      <artifactId>jai-imageio-core</artifactId>
      <version>1.3.1</version>
  </dependency>