Google Code Prettify

2017年3月30日 星期四

在 WebSphere 8.5.5.x 上遇到的 jar 檔版本和衝突問題

最近將自己負責的一個系統升級,升級的項目主要有以下幾項:
  1. JDK: 5.0 升到 8.0
  2. IBM WebSphere Application Server: 6.0 升到 8.5.5.x
  3. spring framework: 2.5.6 升到 4.3.7,且全部的 xml 設定都改為用 annotation。
  4. hibernate: 3.3.x 升到 5.2.4,且程式都用 JPA 改寫。
  5. Ajax: 由 DWR (Direct Web Remoting) 換為 jQuery
當然是有花了一些時間,也請了幾個同事協助修改以加快進度,好不容易改完,要部署到 WAS 時,遇到很多 jar 檔的問題,這裡記錄幾個,下面是安裝過程遇到的錯誤訊息及解決辦法。

遇到這些錯誤從錯誤訊息基本上都可以找到蛛絲馬跡,我用紅色標起來的部份,可以看到因為 jar 檔版本升級或被廠商修改過,程式內容已經不一樣了,造成型別錯誤、找不到該有的 method 等,用這些關鍵字先 google 一下,網路上多半會有人已經找到有問題的 jar 檔,如果 google 不到,就是考驗經驗、實力和耐心的開始了 ...
  • xercesImpl
ServletWrappe E com.ibm.ws.webcontainer.servlet.ServletWrapper init SRVE0271E: 未捕捉到應用程式中Servlet [application] 產生的init() 異常狀況:java.lang.IncompatibleClassChangeError
        at org.dom4j.tree.AbstractElement.setAttributes(AbstractElement.java:505)
        at org.dom4j.io.SAXContentHandler.addAttributes(SAXContentHandler.java:916)
        at org.dom4j.io.SAXContentHandler.startElement(SAXContentHandler.java:249)
        at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source)
        at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
        at org.apache.xerces.impl.XMLNSDocumentScannerImpl$NSContentDispatcher.scanRootElementHook(Unknown Source)
        at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
        at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source) 
怎麼解決? 基本也只能從訊息中猜測,是不是 jar 檔版本太舊沒有更新? 並嘗試更新幾個 jar 檔試看看,最後是把 xercesImpl-2.8.1.jar 升級到 2.9.1 以上版本就可解決了。
  • javax.el-api
webapp        E com.ibm.ws.webcontainer.webapp.WebApp initializeExtensionProcessors SRVE0280E: 在 Factory [com.ibm.ws.jsp.webcontainerext.ws.WASJSPExtensionFactory@f87c2d7d] 中,延伸規格處理器無法起始設定:java.lang.ClassCastException: org.apache.el.ExpressionFactoryImpl incompatible with javax.el.ExpressionFactory
        at javax.el.ExpressionFactory.newInstance(ExpressionFactory.java:210)
        at javax.el.ExpressionFactory.newInstance(ExpressionFactory.java:118)
        at com.ibm.ws.jsp.configuration.JspConfiguration.<init>(JspConfiguration.java:63)
        at com.ibm.ws.jsp.configuration.JspConfigurationManager.createJspConfiguration(JspConfigurationManager.java:202)
        at com.ibm.ws.jsp.taglib.TagLibraryCache.loadWebInfTagFiles(TagLibraryCache.java:444)
        at com.ibm.ws.jsp.taglib.TagLibraryCache.<init>(TagLibraryCache.java:117)
        at com.ibm.ws.jsp.webcontainerext.AbstractJSPExtensionProcessor.<init>(AbstractJSPExtensionProcessor.java:215)
        at com.ibm.ws.jsp.webcontainerext.ws.WASJSPExtensionProcessor.<init>(WASJSPExtensionProcessor.java:81)
        at com.ibm.ws.jsp.webcontainerext.ws.WASJSPExtensionFactory.createProcessor(WASJSPExtensionFactory.java:267)
        at com.ibm.ws.jsp.webcontainerext.AbstractJSPExtensionFactory.createExtensionProcessor(AbstractJSPExtensionFactory.java:76)
        at com.ibm.ws.webcontainer.webapp.WebApp.initializeExtensionProcessors(WebApp.java:1408)
這個猜測是 JSP 上的 EL (Expression Language) 相關的 jar 檔和 WAS 的 jar 檔衝突了,於是找到 java.el-api-2.2.4.jar 將它刪除。事實上,在 war 檔中不應該含有 servlet-api.jar, jsp-api.jar, el-api.jar, j2ee.jar, javaee.jar 這些 jar 檔,否則都會有錯誤。
  • xml-apis
Caused by: javax.xml.parsers.FactoryConfigurationError: Provider javax.xml.parsers.DocumentBuilderFactory could not be instantiated: java.util.ServiceConfigurationError: javax.xml.parsers.DocumentBuilderFactory: Provider org.apache.xerces.jaxp.DocumentBuilderFactoryImpl not a subtype
        at javax.xml.parsers.DocumentBuilderFactory.newInstance(Unknown Source)
        at com.ibm.websphere.product.utils.SimpleXMLParser.getDocumentBuilderWithEntityResolver(SimpleXMLParser.java:760)
        at com.ibm.websphere.product.utils.SimpleXMLParser.<init>(SimpleXMLParser.java:198)
        at com.ibm.websphere.product.utils.SimpleXMLParser.<init>(SimpleXMLParser.java:176)
        at com.ibm.websphere.product.metadata.im.IMMetadata.parseInstalledXmlFile(IMMetadata.java:422)
        at com.ibm.websphere.product.metadata.im.IMMetadata.parseInstallRegistryFiles(IMMetadata.java:364)
這個錯誤看來是和 xml 相關的 jar 檔有關,但是和 xml 有關的 jar 檔很多,很難確定是那一個,會找到 xml-apis-2.0.2.jar,是 google 得到的答案,因為這個 jar 檔和 javax.xml 裡的相關 API 衝突了,刪除這個檔案即可。
  • geronimo-stax-api_1.0_spec-1.0.1.jar
Exception occurred while the JNDI NamingManager was processing a javax.naming.Reference object. [Root exception is javax.xml.stream.FactoryConfigurationError: Provider javax.xml.stream.XMLInputFactory could not be instantiated: java.util.ServiceConfigurationError: javax.xml.stream.XMLInputFactory: Provider com.ctc.wstx.stax.WstxInputFactory not a subtype]
這也是和 xml 有關的 jar 檔衝突,移除 geronimo-stax-api_1.0_spec-1.0.1.jar 即可。
  • persistence-api-1.0.2.jar
Caused by: java.lang.NoSuchMethodError: javax.persistence.spi.PersistenceUnitInfo.getValidationMode()Ljavax/persistence/ValidationMode;
    at org.hibernate.jpa.boot.internal.PersistenceUnitInfoDescriptor.getValidationMode(PersistenceUnitInfoDescriptor.java:88)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.mergeSettings(EntityManagerFactoryBuilderImpl.java:454)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.<init>(EntityManagerFactoryBuilderImpl.java:199)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.<init>(EntityManagerFactoryBuilderImpl.java:163)
看起來是 JPA 相關的 jar 檔版本有衝突,我想用的是 hibernate-jpa-2.1-api-1.0.0.Final.jar,但是實際上用到舊的,找了一下發現是 persistence-api-1.0.2.jar 也有相關的 class,刪除即可。
[see also] 如何在 WebSphere 中解決 jar 包衝突




2017年3月26日 星期日

看見 Angular 的車尾燈

看了這篇是不是就會寫 Angular 程式了? 當然不可能! Angular 的學習門檻算是高的,這篇連 Hello World 都還沒開始,只是讓把開發環境準備好,至少,這樣可以開始學習 Angular 了 ... Orz...

一般的書在介紹 Angular 時,推薦使用的編輯器是 WebStorm、Subline Text 或 Visual Studio Code,但是,對於 Java 的開發者來說,通常使用 eclipse,要在電腦同時開啟 eclipse 和上面三個編輯器中的任何一個,都要電腦性能不錯,不然寶貴的生命會大量浪費在等待,這裡就以 eclipse 來當開發工具。
  • 安裝 Angular plugin
使用 eclipse 中的 Marketplace 搜尋 Angular,可以找到「Angular IDE ...」,將它安裝好 ...
  • 建立一個 Angular 2 Project
使用上方選單「File > New > Angular 2 Project」,建立一個命名為 Party 的專案,輸入專案名稱後按【Finish】,因為它會安裝 Node.js 並設定環境,需要幾分鐘的時間。
  • 啟動伺服器
建立好 Angular 2 Project,就會產生如下圖的許多檔案,並將這個專案安裝於 Angular CLI 中,按一下箭頭所指的綠色三角按鍵以啟動伺服器。

啟動後可以在「Terminal」視窗中看到如下訊息,沒有任何錯誤的話,表示成功啟動。
  • 測試
開啟 Chrome,於網址列輸入 http://localhost:4200,4200 是預設的 port,瀏覽器上應該會顯示如下的訊息,表示程式正常運作。
  • 說明
這裡簡單的說明程式運作的方式,更詳細的會在日後整理的筆記中逐一說明。
  1. src 目錄: 程式放在這個目錄下,至於和這個目錄同一層的一些檔案,如 package.json、tsconfig.json …,這些是開發環境的一些設定。
  2. main.ts: 主程式由這裡開始,重點倒不是這個檔案命名為 main,而是這個程式裡有 boostrapModule,指定了開始的 module。
  3. import { enableProdMode } from '@angular/core';
    import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
    
    import { AppModule } from './app/app.module';
    import { environment } from './environments/environment';
    
    if (environment.production) {
      enableProdMode();
    }
    
    platformBrowserDynamic().bootstrapModule(AppModule);

  4. app.module.ts: 既然上面指定了程式由 AppModule 開始,我們就找到 ./app/app.module.ts,這裡又指定這支程式以 AppComponent 開始。特別注意 @NgModule,一個 SPA 可以有許多個 module,但是若且唯若有一個 @NgModule module,這個是 root module。
  5. import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { FormsModule } from '@angular/forms';
    import { HttpModule } from '@angular/http';
    
    import { AppComponent } from './app.component';
    
    @NgModule({
      declarations: [
        AppComponent
      ],
      imports: [
        BrowserModule,
        FormsModule,
        HttpModule
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
  6. app.component.ts: 開啟這個檔案,可以看到 AppComponent,它有三個重要的參數 selector、templateUrl、styleUrls,分別指出這個 module 定義了一個命名為 app-root 的 tag,並且這個 controller 與 app.compoent.html 相關聯,html 裡套用 app.component.css,黃色 app works! 就是網頁顯示的訊息,接下來要看一下網頁。
  7. import { Component } from '@angular/core';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css']
    })
    export class AppComponent {
      title = 'app works!';
    }

  8. app.component.html: 網頁只是簡單的顯示出 controller 中 model 裡的的值。到這裡至少可以看到 Angular 怎麼運作,但是離要寫出第一支程式恐怕還有一段不短的路要走 …
  9. <h1>
      {{title}}
    </h1>





【日劇 - 全職主婦偵探】
深田恭子主演的愛情喜劇,基本上,深田恭子有多麼的美麗,這是不用多說的了,在看她之前,先看一下劇中演她好友的蘆名星,其實她長得也相當不錯。
既然在劇中扮偵探,變裝是基本的要求,上圖可以看到她的數種變裝,不管那一種一定都非常可愛、非常卡娃伊 (かわいい),日本人看深田恭子,就是要看她美美的、可愛的在劇中出現,演技嘛 ~ 那不是重點啦!
就算扮清潔工,還是這麼可愛,拜託~ 這麼可愛被高階主管看到,會被收去當秘書的啦! 現實生活中當然不會有這種事。
這張當然不是深田恭子,是本田翼,她的演技也很差,靠著亮麗的外表,就可以在一些日劇中有吃重的演出,她看來是打算走深田恭子的路線? 也好啦~ 日劇往往都把劇情編的太沉重,有美女可以看,是可以輕鬆點。