部署 WAR 到 IBM Bluemix 與 Tomcat 上面的執行結果(Context Root)不同原因

其實拿 IBM Bluemix 上面的 WebSphere Liberty Profile 和 Apache Tomcat 相比,是有一點拿雞腿比XX的味道了(誤)。
不過既然資策會的同學問了,我就誠心誠意的來解答吧!

WebSphere Liberty Profile 是完整的 JavaEE 認證過的平台(原廠說明可以 看此 );而 Apache Tomcat 僅有「實做」了 JavaEE 標準中的幾個部分:Java Servlet、JavaServer Pages、Java Expression Language 和 Java WebSocket,真正符合 JavaEE Web Profile 認證的 Apache 軟體,則是 Apache TomEE

所以在 WebSphere Liberty Profile 上跑出和 Apache Tomcat 上不同的結果,其實是蠻常見的事情,不需要太訝異。
在工作上也常常遇到人家這樣問我:「Tomcat 上可以跑,為什麼放到 WebSphere 不行!一定是 WebSphere 有問題!」。
其實這樣的說法就好像你去考一個模擬考出來,說你可以考上這個考試,然後到了正式測驗的時候卻沒有考過,再反過來質疑正式測驗的內容是不是有問題的道理是相同的。

好,廢話不多說,就讓我們來看看在 IBM Bluemix WebSphere Liberty Profile 和 Apache Tomcat 上面,為何相同的 WAR 會跑出不同的結果。

確認 IBM  Bluemix  是否已經配置完成、 Tomcat  是否已經配置完成(在這邊使用  Tomcat8 ,最主要因素是  Tomcat8  所使用的  JavaEE  規格與目前  IBM Bluemix  上面的  WebSphere Liberty Profile  相同)。

6B0B13F7-CA30-4141-BAF1-A349CC8E60C5

建立一個  Dynamic Web Project ,名稱為  javaeedemo2 (名稱可以調整,但不要和  IBM Bluemix  上面的相同即可,在上圖中已經有一個名稱為 javaeedemo 的應用程式了),而且注意不要加入到任何的 EAR 裡面。

71E8989C-5C54-46C2-A857-664145E19FF6

8ECB4703-F558-4D3F-88F2-B167A4210C91

原則上,這個被建立出來的  Dynamic Web Project ,它的  context root  會是  project name ,也就是  javaeedemo2 。怎麼確認?可以在 project 建立完成之後選擇  project ,按下滑鼠右鍵,選擇「 properties 」,再選擇「 Web Project Settings 」,就可以看到 context root 設定了。

6BB4136E-F22D-4502-A164-4F9AA90075D8

17F24BE3-993C-485E-A97F-87FA62F9265D

將這個  javaeedemo2 Dynamic Web Project 掛到  IBM Bluemix  上面去執行。

0BFFE8EF-5076-466F-87D5-50456862C05E

1F3CAB49-D5B5-429B-9096-667EC5F17884

7A4F6D0D-EFA6-4F73-ABB9-406ECC33E212

BF24FFB5-F8BA-4CED-AB64-C33381003F99

243BFEFB-CE5E-49D0-9D48-F038E4E3ECD2

看完這幾個畫面,如果你又曾經在  Tomcat  上面這樣跑過  Dynamic Web Project  的話,應該大概有感覺這兩者最主要的差別在哪裡:
以 IBM Bluemix 來說,javaeedemo2 被掛在一個 sub-domain 執行,因此透過這樣的部署方式部署上去的 Dynamic Web Project,它在 Eclipse 的 context root 設定會失效,IBM Bluemix 預設會把這個 Dynamic Web Project 的 context root 自動綁定在 / 底下。
加一個 HTML 檔案上去執行看看。

DE79C60E-F7EB-42B2-A097-B0F72E6E3CE1

6E0621BC-5E5E-4F20-A043-1720194DBBE9

9A846992-C60C-40CF-9D90-61F136EE6693

B462D26E-C3B6-490D-85BD-221ADFE5B974

7795F84E-463B-40C7-A0B1-5812E1141C5E

07D08E34-34E0-4E89-953E-39991EB4D6C4

F76C2115-5B6E-4C1E-ADD7-2B66C878CAE3

從最後一張圖就可以看出結果與前面的假設相同,IBM Bluemix 會將 Dynamic Web Project 以 / 的 context root 進行部署;這樣的情況,又要怎麼改變呢?
嘗試著在 Eclipse 裡面調整 context root, 選擇 javaeedemo2 這個  project ,按下滑鼠右鍵,選擇「 properties 」,再選擇「 Web Project Settings 」 。
可以看到是 context root 是 javaeedemo2。

22BE3FCE-ECD5-4593-AB76-CBDE7B013CDE

改成 javaeedemo3 看看。

80085723-7BDB-423B-9ACF-4C4D5464F417

重新部署。

8112E87A-196F-45E3-82E1-A7C8AA450B53

再執行看看 index.html。

D363E120-F7D7-47DA-878C-55E0D0501685

顯示 404 錯誤,代表在這個網址找不到這張 HTML。
把網址換成 http://javaeedemo2.mybluemix.net/javaeedemo3/index.html 看看,可以看到正常的結果。

D2C18952-6EB8-4A8C-9EFE-9C6A1958C89B

換到 Apache Tomcat 執行看看,很直覺的就是使用 Eclipse 專案的 context root 去跑了:

1AF59A09-3B55-4A42-80F1-1DD85E5BAF99

0D664840-527B-4B11-B820-66E3182872A7

3EB7A923-C751-45B4-AE0C-150D9479D199

F063BE1E-3CEF-446B-901D-38070CFA2939

9F79FB8D-4833-447B-9FEA-CC76A810F04C

6D8F1C5A-3BE8-42C2-8CB5-BCB82688F445

走到這邊,大概可以歸納出以下幾點:
當我們在 Eclipse 建立新的 Dynamic Web Project,並且將這個 WAR 部署到 IBM Bluemix WebSphere Liberty Profile 的時候,IBM Bluemix 在一開始可能會忽略我們指定的 context root,而將這個 WAR 放在 / 根目錄執行。

我們可以透過修改 Dynamic Web Project 的設定,將 context root 做修改並且重新部署之後,IBM Bluemix WebSphere Liberty Profile 就會接受新的 context root。

這是 IBM Bluemix WebSphere Liberty Profile 的特性,並不是 IBM WebSphere Liberty Profile 的特性,在雲平台上面還是有些許的不同(會以指定 sub-domain 的方式優先)。

在 JavaEE certified 的平台上面跑應用程式,概念上還是建議具備 EAR(Enterprise application ARchive)的概念比較好,不要只有 WAR(Web application ARchive)的概念。

資策會同學來信最主要是問 context root 的問題(因為他們使用了絕對路徑的方式在處理網址或是 form 的 action 屬性),而好的作法應該是用相對路徑去處理這些事情。

因為,在 JavaEE 的標準裡面,負責部署應用程式的管理者,是有機會修改你 WAR(Web application Archive)的 context root 的,所以非必要盡量不要在任何地方使用絕對路徑。