Total Pageviews

2016/06/09

[WAS] WSVR0605W - "Thread may be hung"

Problem
I'm running my web application on IBM WebSphere.
There is a warning message in System.out.log :
 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
[4/25/16 17:16:03:756 CST] 00000068 SystemOut     O [2016-04-25 17:16:03][WARN][Deferrable Alarm : 1][Line:1709][com.ibm.ws.runtime.component.ThreadMonitorImpl.logToJSR47Logger]WSVR0605W: Thread "WebContainer : 6" (000000d3) has been active for 667,910 milliseconds and may be hung.  There is/are 1 thread(s) in total in the server that may be hung.
    at java.io.RandomAccessFile.readBytes(Native Method)
    at java.io.RandomAccessFile.read(RandomAccessFile.java:368)
    at org.apache.fontbox.ttf.BufferedRandomAccessFile.fillBuffer(BufferedRandomAccessFile.java:122)
    at org.apache.fontbox.ttf.BufferedRandomAccessFile.read(BufferedRandomAccessFile.java:160)
    at org.apache.fontbox.ttf.RAFDataStream.read(RAFDataStream.java:162)
    at org.apache.fontbox.ttf.TTFDataStream.read(TTFDataStream.java:263)
    at org.apache.fontbox.ttf.TTFDataStream.readString(TTFDataStream.java:91)
    at org.apache.fontbox.ttf.TTFDataStream.readString(TTFDataStream.java:64)
    at org.apache.fontbox.ttf.TTFParser.readTableDirectory(TTFParser.java:232)
    at org.apache.fontbox.ttf.TTFParser.parse(TTFParser.java:139)
    at org.apache.fontbox.ttf.TTFParser.parse(TTFParser.java:87)
    at org.apache.pdfbox.pdmodel.font.FileSystemFontProvider.addTrueTypeFont(FileSystemFontProvider.java:502)
    at org.apache.pdfbox.pdmodel.font.FileSystemFontProvider.scanFonts(FileSystemFontProvider.java:246)
    at org.apache.pdfbox.pdmodel.font.FileSystemFontProvider.<init>(FileSystemFontProvider.java:225)
    at org.apache.pdfbox.pdmodel.font.FontMapperImpl$DefaultFontProvider.<clinit>(FontMapperImpl.java:132)
    at java.lang.J9VMInternals.initializeImpl(Native Method)
    at java.lang.J9VMInternals.initialize(J9VMInternals.java:236)
    at org.apache.pdfbox.pdmodel.font.FontMapperImpl.getProvider(FontMapperImpl.java:151)
    at org.apache.pdfbox.pdmodel.font.FontMapperImpl.findFont(FontMapperImpl.java:415)
    at org.apache.pdfbox.pdmodel.font.FontMapperImpl.getTrueTypeFont(FontMapperImpl.java:323)
    at org.apache.pdfbox.pdmodel.font.PDTrueTypeFont.<init>(PDTrueTypeFont.java:198)
    at org.apache.pdfbox.pdmodel.font.PDFontFactory.createFont(PDFontFactory.java:75)
    at org.apache.pdfbox.pdmodel.PDResources.getFont(PDResources.java:123)
    at org.apache.pdfbox.contentstream.operator.text.SetFontAndSize.process(SetFontAndSize.java:60)
    at org.apache.pdfbox.contentstream.PDFStreamEngine.processOperator(PDFStreamEngine.java:815)
    at org.apache.pdfbox.contentstream.PDFStreamEngine.processStreamOperators(PDFStreamEngine.java:472)
    at org.apache.pdfbox.contentstream.PDFStreamEngine.processStream(PDFStreamEngine.java:446)
    at org.apache.pdfbox.contentstream.PDFStreamEngine.processPage(PDFStreamEngine.java:149)
    at org.apache.pdfbox.rendering.PageDrawer.drawPage(PageDrawer.java:189)
    at org.apache.pdfbox.rendering.PDFRenderer.renderPage(PDFRenderer.java:208)
    at org.apache.pdfbox.rendering.PDFRenderer.renderImage(PDFRenderer.java:139)
    at org.apache.pdfbox.rendering.PDFRenderer.renderImageWithDPI(PDFRenderer.java:94)

And my function is hung after I click execute button.


How-to
You need to log into WAS administration console, then go to Servers > Application Servers > server_name. Click Administration > Custom Properties Under Server Infrastructure.

And add four arbitrates

  • com.ibm.websphere.threadmonitor.interval: 180
  • com.ibm.websphere.threadmonitor.threshold: 600
  • com.ibm.websphere.threadmonitor.false.alarm.threshold: 100
  • com.ibm.websphere.threadmonitor.dump.java: false



Remember to save attributes and restart WAS.

But this is just a workaround solution, it may means your programs may consume lots of memory for some reasons. You still need to figure out its root causes and fix them.


Reference
[1] http://websphere-solutions.blogspot.tw/2011/10/hung-threads.html

2016/06/08

[AngularJS] How to add tooltips in ng-grid

Problem
I implemented a data grid by ng-grid as bellows:


The problem is if the length of data is larger than the width of column, it will show ... then ignore the rest of information. Our customer requests to show complete information in tooltips as he/she move cursor on it.

The code snippet of ng-grid 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
$scope.gridCols  = [ 
 {
     field : 'sourceName',
     width : '10%',
     displayName : '來源系統',
     cellClass : 'text-left'
 }, {
     field : 'policyNumber',
     width : '10%',
     displayName : '保單號碼',
     cellClass : 'text-left'
 },{
     field : 'exeMsg',
     width : '65%',
     displayName : '執行訊息',
     cellClass : 'text-left'
 },{
     field : 'exeTime',
     width : '15%',
     displayName : '執行時間',
     cellFilter : "date:'yyyy-MM-dd HH:mm:ss'",
     cellClass : 'text-left'
 }];
 
 $scope.dataGrid = {
     multiSelect : false,
     data : 'itemData',
     columnDefs : 'gridCols',
     enableColumnResize: true,
     enableRowSelection: true,
     rowHeight : 40
 };


How-to
There has two steps to fulfill this requirement.
Step 1. add css in HTML page
1
2
3
4
5
6
7
   <style type="text/css">
    .tooltip-inner {
      text-align: left;
      white-space: pre-wrap;
      max-width: none;
    }
    </style>

Step 2. Modify the ng-grid, and add cellTemplate to show complete information
 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
 var exeMsgCellTemplate='<span tooltip="{{row.entity.exeMsg}}" tooltip-append-to-body="true" tooltip-trigger:"focus"><div style="vertical-align : middle;"  class="ngCellText">{{row.entity.exeMsg}}</div></span>';
 var exeTimeCellTemplate='<span tooltip="{{row.entity.exeTime|date:\'yyyy-MM-dd HH:mm:ss\'}}" tooltip-append-to-body="true" tooltip-trigger:"focus"><div style="vertical-align : middle;"  class="ngCellText">{{row.entity.exeTime|date:\'yyyy-MM-dd HH:mm:ss\'}}</div></span>';
               
 $scope.gridCols  = [ 
 {
     field : 'sourceName',
     width : '10%',
     displayName : '來源系統',
     cellClass : 'text-left'
 }, {
     field : 'policyNumber',
     width : '10%',
     displayName : '保單號碼',
     cellClass : 'text-left'
 },{
     field : 'exeMsg',
     width : '65%',
     displayName : '執行訊息',
     cellClass : 'text-left',
     cellTemplate : exeMsgCellTemplate
 },{
     field : 'exeTime',
     width : '15%',
     displayName : '執行時間',
     cellFilter : "date:'yyyy-MM-dd HH:mm:ss'",
     cellClass : 'text-left',
     cellTemplate : exeTimeCellTemplate
 }];
 
 $scope.dataGrid = {
     multiSelect : false,
     data : 'itemData',
     columnDefs : 'gridCols',
     enableColumnResize: true,
     enableRowSelection: true,
     rowHeight : 40
 };



Check the result:





Reference
[1] http://www.w3schools.com/cssref/pr_text_white-space.asp



2016/06/07

[PDFBox] Utilize Apache PDFBox to Convert PDF to TIF

Requirement
We have an requirement to convert a PDF file to TIF file(s). 
If PDF has 3 pages, it should generate 3 TIF files with 300 DPI. 
For instance, a Getting Started.pdf has 4 pages,it should convert to 4 TIF files, including Getting Started.pdf_01.tifGetting Started.pdf_02.tifGetting Started.pdf_03.tif, and Getting Started.pdf_04.tif.


How-to
We can utilize Apache PDFBox to fulfill this requirement.

You should add maven dependency in your pom.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
        <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>


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
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;
    }

}


Reference
[1] https://pdfbox.apache.org/

2016/06/06

[Java] Encryption and Decryption with AES

Problem
If we have to save some configuration-related data into database table, our customer asks us to do encryption before we save into database if it is password-related information.

Some other function will retrieve user name and password to do authentication, we need to do decryption .


Solution
Here has sample code, using AES to do encryption and decryption:
 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
package albert.practice.encrypt;

import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.codec.binary.Base64;

@Slf4j
public class AESUtils {

    private static String secretKey = "your key";

    public static String encryptText(String plainText) {
        byte[] raw;
        String encryptedString = "";
        SecretKeySpec skeySpec;
        byte[] encryptText = plainText.getBytes();
        Cipher cipher;
        raw = Base64.decodeBase64(secretKey);
        skeySpec = new SecretKeySpec(raw, "AES");
        try {
            cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
            encryptedString = Base64.encodeBase64String(cipher.doFinal(encryptText));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        } catch (NoSuchPaddingException e) {
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException(e);
        } catch (IllegalBlockSizeException e) {
            throw new RuntimeException(e);
        } catch (BadPaddingException e) {
            throw new RuntimeException(e);
        }

        return encryptedString;

    }

    public static String decryptText(String encryptedText) {
        Cipher cipher;
        String encryptedString;
        byte[] encryptText = null;
        byte[] raw;
        SecretKeySpec skeySpec;
        raw = Base64.decodeBase64(secretKey);
        skeySpec = new SecretKeySpec(raw, "AES");
        encryptText = Base64.decodeBase64(encryptedText);
        try {
            cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec);
            encryptedString = new String(cipher.doFinal(encryptText));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        } catch (NoSuchPaddingException e) {
            throw new RuntimeException(e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException(e);
        } catch (IllegalBlockSizeException e) {
            throw new RuntimeException(e);
        } catch (BadPaddingException e) {
            throw new RuntimeException(e);
        }

        return encryptedString;
    }

    public static void main(String[] args) throws NoSuchPaddingException, GeneralSecurityException {
        String plainText = "test123";
        String encryptedText = AESUtils.encryptText(plainText);
        String decryptedText = AESUtils.decryptText(encryptedText);

        log.debug("plainText = " + plainText);
        log.debug("encryptedText = " + encryptedText);
        log.debug("decryptedText = " + decryptedText);
    }
}

Execution result:
1
2
3
2016-04-20 14:06:50.239 [main] DEBUG albert.practice.encrypt.AESUtils - plainText = test123
2016-04-20 14:06:50.255 [main] DEBUG albert.practice.encrypt.AESUtils - encryptedText = P25QKVFoX00OXs5GMOTAhg==
2016-04-20 14:06:50.255 [main] DEBUG albert.practice.encrypt.AESUtils - decryptedText = test123


Reference
[1] http://stackoverflow.com/questions/17567996/illegal-block-size-exception-input-length-must-be-multiple-of-16-when-decrypting

2016/06/05

[Java] error: unmappable character for encoding MS950

Problem
As I try to compile Java class via command line, it throws unmappable character for encoding MS950 error as bellows:


How-to
Assign encoding as you compile:


Reference
[1] http://silverbulletwo.blogspot.tw/2014/11/java-error-unmappable-character-for.html