Fenriswolf 程式筆記

奮利斯狼的地盤,小綿羊勿入

Jetty JNDI 設定

在 Jetty 中如果使用一般 EJB 的方式來存取 JNDI 的 resources 會發現不能用

如果自己 new InitialContext() 並用 getEnvironemnt() method 讀出所有的參數會發現 Jetty 預設已指定了兩個值

java.naming.factory.initial=org.mortbay.naming.InitialContextFactory
java.naming.factory.url.pkgs=org.mortbay.naming

但用 “java:comp/env" 的方式 lookup 在 Jetty 中是一個選用的功能,如果不啟用的話,在 web.xml 裡定義以下的 tags 也是無法找到所定義的資源

<env-entry/>
<resource-ref/>
<resource-env-ref/>

1. 啟用 JNDI
1.a. 以全域的方式設定,表示所有的 applications 都會啟用 JNDI
把以下的內容加入 JETTY_HOME/etc/jetty.xml,在 Jetty 6 及 7 啟用會有一點差異
Jetty 6
新增一個陣列

<Array id="plusConfig" type="java.lang.String">
  <Item>org.mortbay.jetty.webapp.WebInfConfiguration</Item>
  <Item>org.mortbay.jetty.plus.webapp.EnvConfiguration</Item>
  <Item>org.mortbay.jetty.plus.webapp.Configuration</Item>
  <Item>org.mortbay.jetty.webapp.JettyWebXmlConfiguration</Item>
  <Item>org.mortbay.jetty.webapp.TagLibConfiguration</Item>
</Array>

找到如下的定義,設定 configurationClasses 並指定上面定義的陣列

<Call name="addLifeCycle">
  <Arg>
    <New class="org.mortbay.jetty.deployer.WebAppDeployer">
      <Set name="contexts"><Ref id="Contexts"/></Set>
      <Set name="webAppDir"><SystemProperty name="jetty.home" default="."/>/webapps</Set>
      <Set name="parentLoaderPriority">false</Set>
      <Set name="extract">true</Set>
      <Set name="allowDuplicates">false</Set>
      <Set name="defaultsDescriptor"><SystemProperty name="jetty.home" default="."/>/etc/webdefault.xml</Set>
      <Set name="configurationClasses"><Ref id="plusConfig"/></Set>
    </New>
  </Arg>
</Call>

Jetty 7
加入一個陣列。除了 package 名稱都換成 eclipse 之外,要加入的 classes 也變多了

<Array id="plusConfig" type="java.lang.String">
  <Item>org.eclipse.jetty.webapp.WebInfConfiguration</Item>
  <Item>org.eclipse.jetty.webapp.WebXmlConfiguration</Item>
  <Item>org.eclipse.jetty.webapp.MetaInfConfiguration</Item>
  <Item>org.eclipse.jetty.webapp.FragmentConfiguration</Item>
  <Item>org.eclipse.jetty.plus.webapp.EnvConfiguration</Item>
  <Item>org.eclipse.jetty.plus.webapp.PlusConfiguration</Item>
  <Item>org.eclipse.jetty.webapp.JettyWebXmlConfiguration</Item>
  <Item>org.eclipse.jetty.webapp.TagLibConfiguration</Item>
</Array>

直接 call setAttribute 並傳入定義的陣列

<Call name="setAttribute">
  <Arg>org.eclipse.jetty.webapp.configuration</Arg>
  <Arg>
    <Ref id="plusConfig"/>
  </Arg>
</Call>

1.b. 針對單一的 application
只要建立該 application 專屬的 context XML 檔案並放到 JETTY_HOME/contexts 目錄下
範例可參考 contexts 目錄下的 test.xml 及 test-jndi.xml。陣列的定義方式跟上面一樣就不贅述
Jetty 6

<Configure id='wac' class="org.mortbay.jetty.webapp.WebAppContext">
  <Set name="configurationClasses"><Ref id="plusConfig"/></Set>
</Configure>

Jetty 7

<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
  <Set name="configurationClasses"><Ref id="plusConfig"/></Set>
</Configure>

可以看出 1.a 及 1.b 都是定義一樣的陣列,只是一個設定在 Server class,另一個設定在 WebAppContext class。這就是為什麼兩者適用範圍不一樣。更多的設定範例可參考 JETTY_HOME/etc/jetty-plus.xml
接下來是啟動 Jetty server
Jetty 6

java -jar start.jar

至於能不能在 start.jar 參數後面接多個 xml 檔案? 例如

java -jar start.jar etc/jetty.xml etc/jetty-plus.xml

答案是不行的,因為在這兩個檔案內的 WebAppDeployer 被重複定義,所以 jetty-plus.xml 裡的定義會被忽略,也就不會啟用 JNDI 了,所以需合併 jetty-plus.xml 到 jetty.xml

Jetty 7

java -jar start.jar OPTIONS=plus

想少打 OPTIONS 參數的話,可以直接修改 JETTY_HOME/start.ini 檔案,在 OPTIONS 後加入 plus,預設是沒有啟用的

2. 設定 JNDI 資源
在 Jetty 中要設定資源有三種方式
2.a. JETTY_HOME/etc/jetty.xml
一般由系統管理者設定
這部分還細分成 JVM 或 server scope
JVM scope 是當同一個 JVM 同時啟動多個 jetty server 而且彼此要共享 JNDI 資源才會用到
server scope 就是同一個 jetty server 中共享資源,常見的做法都是一個 JVM 起一個 server,因此設定哪個 scope 效果是一樣的
可把這個 scope 看做是全域的,也就是所有的 applications 都可以 lookup 到
如果有第三方的 jar 檔要放在 JETTY_HOME/lib/ext 目錄下

2.b. JETTY_HOME/contexts 下的 context XML 檔案
一般由 application 部署者設定並在部署 application 前寫入 context xml 檔案
只有該 application 可以 lookup 到,這個範圍是可以修改的,就如同 2.a 的設定。但是不建議這樣做,有需要請用 2.a 的方式設定
如果有第三方的 jar 檔要放在 JETTY_HOME/lib/ext 目錄下

2.c. WAR 檔內的 WEB-INF/jetty-env.xml
可由 application 提供者自行設定部署的資源
只有該 application 可以 lookup 到,這個範圍是可以修改的,就如同 2.a 的設定。但是不建議這樣做,有需要請用 2.a 的方式設定
這是最有彈性的做法,系統管理員只要提供一個 Jetty server 即可
第三方 jar 檔只需放在 WEB-INF/lib 目錄

如果不在乎放哪裡的話可擇一使用。Jetty 的設定檔格式都是一樣的,所以以下設定皆可放在這三種設定檔內
如果有同名的資源,預設存取順序會是 jetty-env.xml > context xml > jetty.xml > web.xml,但最好的做法是同名的資源不要放在多個位置造成錯亂
常用的資源型別有兩種
1. org.mortbay.jetty.plus.naming.EnvEntry: 對應到 web.xml 裡的 env-entry tag
2. org.mortbay.naming.plus.Resource: 對應到 web.xml 裡的 resource-ref 及 resource-env-ref tags
以下的例子指定了一個簡單的 EnvEntry 及一個 Derby EmbeddedDataSource。如果要設定更複雜的 connection pool 或不同 database 的 data source 請看參考資料

Jetty 6

<Configure id='wac' class="org.mortbay.jetty.webapp.WebAppContext">
  <New class="org.mortbay.jetty.plus.naming.EnvEntry">
    <Arg><Ref id="wac"/></Arg>
    <Arg>mySpecialValue</Arg>
    <Arg type="java.lang.Integer">4000</Arg>
    <Arg type="boolean">true</Arg>
  </New>
 
  <New class="org.mortbay.jetty.plus.naming.Resource">
    <Arg><Ref id="wac"/></Arg>
    <Arg>jdbc/myds</Arg>
    <Arg>
      <New class="org.apache.derby.jdbc.EmbeddedDataSource">
        <Set name="DatabaseName">test</Set>
        <Set name="createDatabase">create</Set>
      </New>
    </Arg>
  </New>
</Configure>

Jetty 7

<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
  <New class="org.eclipse.jetty.plus.jndi.EnvEntry">
    <Arg><Ref id="wac"/></Arg>
    <Arg>mySpecialValue</Arg>
    <Arg type="java.lang.Integer">4000</Arg>
    <Arg type="boolean">true</Arg>
  </New>
 
  <New class="org.eclipse.jetty.plus.jndi.Resource">
    <Arg><Ref id="wac"/></Arg>
    <Arg>jdbc/myds</Arg>
    <Arg>
      <New class="org.apache.derby.jdbc.EmbeddedDataSource">
        <Set name="DatabaseName">test</Set>
        <Set name="createDatabase">create</Set>
      </New>
    </Arg>
  </New>
</Configure>

EnvEntry 及 Resource 參數定義
1. scope,上面的範例是指定 WebAppContext,就是只有該 application 才讀的到。適合用在 context xml 及 jetty-env.xml,要注意的是 wac 這個 id 預設是沒有給的,請自行加入這個屬性到 Configure tag 裡
如果要設定在 jetty.xml,第一個參數可給空值(JVM scope) 或 server id (server scope),server id 請看設定檔最上方 Configure tag 裡的 id 屬性,預設值是 “Server"
2. JNDI 名稱
3. 資源型別及值
4. 是否覆蓋 web.xml 內的同名設定的值,這是 EnvEntry 特別的參數,因為 Resource 的值無法單獨定義在 web.xml 內,只能用參考(reference)的方式設定

3. 設定 web.xml
EnvEntry 不需要設定在 web.xml 裡就可以用 JNDI 找到,這邊定義的值其實會被覆蓋掉。而 Resource 就一定要在 web.xml 裡明確定義

<web-app>
  <!-- 此定義會被覆蓋 -->
  <env-entry>
    <env-entry-name>mySpecialValue</env-entry-name>
    <env-entry-value>5000</env-entry-value>
    <env-entry-type>java.lang.Integer</env-entry-type>
  </env-entry>
  
  <resource-ref>
    <res-ref-name>jdbc/myds</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
  </resource-ref>
</web-app>

4. 寫一支 servlet 或 jsp 來測試

InitialContext ic = new InitialContext();
Integer mySpecialValue = (Integer)ic.lookup("java:comp/env/mySpecialValue");
DataSource myDS = (DataSource)ic.lookup("java:comp/env/jdbc/myds");

 
 
執行環境
JDK 1.6.0_24
Jetty 6.1.26
Jetty 7.4.3

參考資料
Jetty 6 JNDI
Jetty 7 JNDI
設定 JNDI Data Source

廣告

2012/03/21 - Posted by | Application Server | ,

仍無迴響。

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

w

連結到 %s

%d 位部落客按了讚: