自從阿里云推出函數(shù)計算(FC)以來,一直期待著能用Java語言實現(xiàn)FC,今年早些時候發(fā)現(xiàn)已經(jīng)放出了Java FC的實現(xiàn),這樣我們的DICOM預(yù)處理就可以做成函數(shù)了。這周終于空閑下來,決定來踩坑。
按照阿里云Java教程很容易寫了一個DemoFC,不過在用fcli發(fā)布函數(shù)的時候該教程的命令是不太對的,mkf 命令應(yīng)該使用參數(shù) -f YourPackage.jar 來指定要上傳的jar包。完整的命令如下:
?mkf demo-java -t java8 -h com.lifeccp.fc.dcmpp.DemoFC::handleRequest -f fc-dcmpp-1.0.0.jar
接下來就開始將dcm4che引入項目了。
首先遇到的第一個坑是maven不能下載dcm4che。
Java and Let's Encrypt Certificates
DCM4CHE自己有一個maven repository,啟用了HTTPS,并且使用的是Let's Encrypt的證書(全世界碼農(nóng)的選擇都一樣)。JDK8U101之前的版本沒有裝入Let's Encrypt的根證書,導(dǎo)致maven下載依賴包的時候出錯:
Failed to collect dependencies at org.dcm4che:dcm4che-core:jar:5.14.0: Failed to read artifact descriptor for org.dcm4che:dcm4che-core:jar:5.14.0: Could not transfer artifact org.dcm4che:dcm4che-core:pom:5.14.0 from/to www.dcm4che.org (https://www.dcm4che.org/maven2/): sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
最簡單的解決辦法:升級JDK到8U101以后版本。
參考這篇blog: https://www.compose.com/articles/compose-notes-java-and-lets-encrypt-certificates/
OpenCV
Java底下一直沒有很好的JPEGLS/JPEG2K支持,之前dcm4che用的是一個很久不更新的jai_imageio(版本1.2-pre-dr-b04,對,一直停留在pre-b04版本號上),而且底層還依賴clipwrap的jni,這個native依賴常常讓預(yù)處理器崩潰。dcm4che 5.0以后引入了OpenCV這個強(qiáng)大的圖像庫來提供圖像IO,我們在生產(chǎn)環(huán)境上升級dcm4che 5.0以后,處理JPG編碼的DICOM沒有再奔潰了。不過OpenCV還是native依賴的,不知道阿里云的FC環(huán)境是否能夠支持呢?
先試試再說,加上opencv依賴:
<dependency>
? ? ? ? ? ? <groupId>org.dcm4che</groupId>
? ? ? ? ? ? <artifactId>dcm4che-imageio-opencv</artifactId>
? ? ? ? ? ? <version>5.14.0</version>
? </dependency>??
構(gòu)建過程中并沒有自動包native包拉進(jìn)來,還得將需要的native包依賴上才行。雖然構(gòu)建后發(fā)現(xiàn)已經(jīng)將libopencv_java-3.4.0-dcmR3-linux-x86-64.so 拷貝到lib了,但還是找不到opencv_java的本地依賴包。上面的方法拷貝的.so文件名并不是OpenCV core去加載的文件名,還得把名稱改成libopencv_java.so (在mac則是libopencv_java.jnilib)才行。使用maven-dependenciey-plugin:copy 來完成。
<plugin>
? ? ? ? ? ? ? ? <groupId>org.apache.maven.plugins</groupId>
? ? ? ? ? ? ? ? <artifactId>maven-dependency-plugin</artifactId>
? ? ? ? ? ? ? ? <version>3.1.1</version>
? ? ? ? ? ? ? ? <executions>
? ? ? ? ? ? ? ? ? ? <execution>
? ? ? ? ? ? ? ? ? ? ? ? <id>copy-dependencies</id>
? ? ? ? ? ? ? ? ? ? ? ? <phase>prepare-package</phase>
? ? ? ? ? ? ? ? ? ? ? ? <goals>
? ? ? ? ? ? ? ? ? ? ? ? ? ? <goal>copy-dependencies</goal>
? ? ? ? ? ? ? ? ? ? ? ? </goals>
? ? ? ? ? ? ? ? ? ? ? ? <configuration>
? ? ? ? ? ? ? ? ? ? ? ? ? ? <outputDirectory>${project.build.directory}/classes/lib</outputDirectory>
? ? ? ? ? ? ? ? ? ? ? ? ? ? <includeScope>runtime</includeScope>
? ? ? ? ? ? ? ? ? ? ? ? </configuration>
? ? ? ? ? ? ? ? ? ? </execution>
? ? ? ? ? ? ? ? ? ? <!-- copy libopencv_java.so for linux-x86-64 for distribution and testing,
? ? ? ? ? ? ? ? ? ? run package goal once before test on linux, otherwise vm can't find native library -->
? ? ? ? ? ? ? ? ? ? <execution>
? ? ? ? ? ? ? ? ? ? ? ? <id>copy</id>
? ? ? ? ? ? ? ? ? ? ? ? <phase>prepare-package</phase>
? ? ? ? ? ? ? ? ? ? ? ? <goals>
? ? ? ? ? ? ? ? ? ? ? ? ? ? <goal>copy</goal>
? ? ? ? ? ? ? ? ? ? ? ? </goals>
? ? ? ? ? ? ? ? ? ? ? ? <configuration>
? ? ? ? ? ? ? ? ? ? ? ? ? ? <artifactItems>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <artifactItem>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <groupId>org.weasis.thirdparty.org.opencv</groupId>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <artifactId>libopencv_java</artifactId>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <type>so</type>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <version>${weasis.opencv.native.version}</version>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <classifier>linux-x86-64</classifier>? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <outputDirectory>${project.build.directory}/classes/lib</outputDirectory>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <destFileName>libopencv_java.so</destFileName>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? </artifactItem>
? ? ? ? ? ? ? ? ? ? ? ? ? ? </artifactItems>
? ? ? ? ? ? ? ? ? ? ? ? </configuration>
? ? ? ? ? ? ? ? ? ? </execution>
? ? ? ? ? ? ? ? ? ? <!-- copy libopencv_java.jnilib for macosx-x86-64 for testing under my Mac -->
? ? ? ? ? ? ? ? ? ? <execution>
? ? ? ? ? ? ? ? ? ? ? ? <id>copy-mac</id>
? ? ? ? ? ? ? ? ? ? ? ? <phase>process-test-classes</phase>
? ? ? ? ? ? ? ? ? ? ? ? <goals>
? ? ? ? ? ? ? ? ? ? ? ? ? ? <goal>copy</goal>
? ? ? ? ? ? ? ? ? ? ? ? </goals>
? ? ? ? ? ? ? ? ? ? ? ? <configuration>
? ? ? ? ? ? ? ? ? ? ? ? ? ? <artifactItems>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <artifactItem>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <groupId>org.weasis.thirdparty.org.opencv</groupId>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <artifactId>libopencv_java</artifactId>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <type>jnilib</type>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <version>${weasis.opencv.native.version}</version>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <classifier>macosx-x86-64</classifier>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <outputDirectory>${project.build.directory}/test-classes/lib</outputDirectory>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <destFileName>libopencv_java.jnilib</destFileName>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? </artifactItem>
? ? ? ? ? ? ? ? ? ? ? ? ? ? </artifactItems>
? ? ? ? ? ? ? ? ? ? ? ? </configuration>
? ? ? ? ? ? ? ? ? ? </execution>
? ? ? ? ? ? ? ? </executions>
? ? ? ? ? ? </plugin>
同時需要配置maven-surefire-plugin ,加上<argLine>-Djava.library.path=./target/test-classes/lib:./target/classes/lib</argLine>,不然test的時候還是找不到本地依賴,mvn -Djava.library.path=./target/test-classes/lib? 指定都不管用,因為test啟動的是另外的vm。
? <!-- specify java.library.path for testing -->
? ? ? ? ? ? <plugin>
? ? ? ? ? ? ? ? <groupId>org.apache.maven.plugins</groupId>
? ? ? ? ? ? ? ? <artifactId>maven-surefire-plugin</artifactId>
? ? ? ? ? ? ? ? <version>2.22.0</version>
? ? ? ? ? ? ? ? <configuration>
? ? ? ? ? ? ? ? ? ? <argLine>-Djava.library.path=./target/test-classes/lib:./target/classes/lib</argLine>
? ? ? ? ? ? ? ? </configuration>
? ? ? ? ? ? </plugin>
接下來就是激動人心的上FC真實環(huán)境測試了。按照上面pom的配置,libopencv_java.so 拷貝到lib目錄并且打包到j(luò)ar以后,vm能夠成功加載native包。FC上的Java runtime:
user.dir:/code
java.library.path:/code/:/code//lib:/usr/java/packages/lib/amd64:/usr/lib/x86_64-linux-gnu/jni:/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu:/usr/lib/jni:/lib:/usr/lib
>fcli shell
Welcome to the function compute world. Have fun!
>>> cd deidentifier
>>> ls
dcminfo
demo-java
>>> invk dcminfo -s samples/CT1_J2KR
loading native library:opencv_java...
native library loaded.
samples/CT1_J2KR 512x512px
color model:ColorModel: #pixelBits = 8 numComponents = 1 color space = java.awt.color.ICC_ColorSpace@12ab536b transparency = 1 has alpha = false isAlphaPre = false
Job done!?