JBoss Fuse –一些鲜为人知的技巧
TL; DR
將Java靜態調用公開為Karaf Shell本機命令
作為必須與支持人員和客戶進行協作的軟件工程師的一部分,我經常發現自己需要從無法訪問的系統中提取其他信息。 通常適用于所有軟件的方法通常是提取日志,調用交互式命令以獲得特定的輸出,或者在最復雜的情??況下,部署一些PoC單元來驗證特定行為。
JBoss Fuse和Karaf所基于的平臺在公開所有這些數據方面做得非常好。
你有:
- 大量日志并與Log4j集成
- jmx操作的詳盡列表(您最終可以使用jolokia通過http調用)
- 大量的Shell命令
但是有時候這還不夠。 如果您看過我以前有關如何在JBoss Fuse上使用Byteman的文章,則可以想象所有其他情況:
Byteman仍然是一個很好的選擇,但是Karaf具有一種可用于運行自定義代碼的工具 。
Karaf,允許您直接在其shell中編寫代碼; 并允許您將這些代碼位記錄為可以重新調用的宏。 這個宏看起來像一個原生的Karaf shell命令!
讓我們看一個我必須實現的真實示例:
驗證運行我的JBoss Fuse實例的jvm是否正在按預期解析特定的DNS。
標準JDK具有可用來解析dns名稱的方法: InetAddress.gettAllByName(String)
由于該命令非常簡單,這意味著它不需要復雜或結構化的輸入,我想我可以將其變成易于重用的命令:
# add all public static methods on a java class as commands to the namespace "my_context": # bundle 0 is because system libs are served by that bundle classloader addcommand my_context (($.context bundle 0) loadClass java.net.InetAddress)該時髦的行用以下方式解釋:
- addcommand是接受新命令的karaf shell功能
- my_context是您要附加命令的名稱空間/前綴。 就我而言,“ dns”將成為一個好的名稱空間。 ($.context bundle 0)調用Java代碼。 特別是,我們正在調用$.context實例,該實例是Karaf shell公開的內置實例,用于暴露OSGi框架,其類型為org.apache.felix.framework.BundleContextImpl ,并且正在調用其方法,稱為bundle pass參數0代表負責加載JDK類的OSGi類加載器的ID。 該調用返回org.apache.felix.framework.Felix的實例,可用于加載所需的特定類定義,即java.net.InetAddress 。
就像內聯注釋所說的那樣,調用addcommand公開該類上的所有公共靜態方法 。 因此,現在允許我們調用這些方法,尤其是可以解析dns條目的方法:
JBossFuse:karaf@root> my_context:getAllByName "www.google.com" www.google.com/74.125.232.146 www.google.com/74.125.232.145 www.google.com/74.125.232.148 www.google.com/74.125.232.144 www.google.com/74.125.232.147 www.google.com/2a00:1450:4002:804:0:0:0:1014此功能在Karaf文檔頁面上進行了描述。
在部署時覆蓋OSGi標頭
如果您與Karaf合作,那么您正在使用OSGi,喜歡或討厭它 。 每個OSGi工作流程中的一個典型步驟是播放(或戰斗) OSGi標頭 。 如果您完全控制項目,則這可能會或多或少容易,具體取決于部署單元之間的關系。 請參閱Christian Posta的帖子 ,以瞥見一些不明顯的例子。
在這些情況下,一種非常典型的情況是必須使用捆綁包,您自己或他人的捆綁包 ,并且捆綁包頭不正確 。 最終要做的通常是重新打包該捆綁包,以便您可以更改其MANIFEST的內容 ,以添加所需的OSGi標頭。
Karaf在這方面具有一種設施,稱為wrap協議。 您可能已經知道,這是在Karaf上部署非捆綁jar的快捷方式,但實際上不僅限于此 。
顧名思義,它真正要做的就是包裝。 但是它可以同時包裹非捆綁包和捆綁包! 這意味著我們還可以使用它來更改我們將要安裝的已打包捆綁包的元數據。
讓我們舉個例子,再次從現實生活中獲得經驗。 Apache HttpClient并非完全OSGi友好。 我們可以使用wrap:協議將其安裝在Karaf上,并導出所有軟件包 。
JBossFuse:karaf@root> install -s 'mvn:org.apache.httpcomponents/httpclient/4.2.5' Bundle ID: 257 JBossFuse:karaf@root> exports | grep -i 257257 No active exported packages. This command only works on started bundles, use osgi:headers instead JBossFuse:karaf@root> install -s 'wrap:mvn:org.apache.httpcomponents/httpclient/\ 4.2.5$Export-Package=*; version=4.2.5' Bundle ID: 259 JBossFuse:karaf@root> exports | grep -i 259259 org.apache.http.client.entity; version=4.2.5259 org.apache.http.conn.scheme; version=4.2.5259 org.apache.http.conn.params; version=4.2.5259 org.apache.http.cookie.params; version=4.2.5 ...我們可以看到它也適用于普通捆綁包 :
JBossFuse:karaf@root> la -l | grep -i camel-core [ 142] [Active ] [ ] [ ] [ 50] mvn:org.apache.camel/camel-core/2.12.0.redhat-610379 JBossFuse:karaf@root> install -s 'wrap:mvn:org.apache.camel/camel-core/2.12.0.redhat-610379\ $overwrite=merge&Bundle-SymbolicName=paolo-s-hack&Export-Package=*; version=1.0.1' Bundle ID: 269JBossFuse:karaf@root> headers 269camel-core (269) ---------------- ...Bundle-Vendor = Red Hat, Inc. Bundle-Activator = org.apache.camel.impl.osgi.Activator Bundle-Name = camel-core Bundle-DocURL = http://redhat.com Bundle-Description = The Core Camel Java DSL based routerBundle-SymbolicName = paolo-s-hackBundle-Version = 2.12.0.redhat-610379 Bundle-License = http://www.apache.org/licenses/LICENSE-2.0.txt Bundle-ManifestVersion = 2...Export-Package = org.apache.camel.fabric;uses:="org.apache.camel.util,org.apache.camel.model,org.apache.camel,org.apache.camel.processor,org.apache.camel.api.management,org.apache.camel.support,org.apache.camel.spi";version=1.0.1,...在哪里可以看到Bundle-SymbolicName并且導出的軟件包的版本帶有我設置的值。
同樣,該功能在Karaf文檔中進行了描述,您可能會發現包裝協議參考非常有用。
在使用OSGi片段部署時間后覆蓋OSGi標頭
最后一個技巧很強大,但是如果您不想冒險讓一個類加載器暴露一半的類,而讓另一個類加載器暴露剩余的類(那些您可能已在重寫的Export添加的包),則可能需要您刪除原始包。一。
實際上,有一種更好的方法來覆蓋OSGi標頭,它直接來自OSGi標準功能: OSGi Fragments 。
如果您不熟悉此概念,則直接取自OSGi Wiki的定義是:
捆綁包片段(或簡稱為片段)是一個捆綁包,其內容可用于另一個捆綁包(片段主機)。 重要的是,片段共享其父捆綁的類加載器。
該頁面還提供了有關我將要描述的內容的進一步提示:
有時,片段用于“修補”現有的捆綁包。
我們可以使用此策略來:
- 在目標包的類路徑中注入.jars
- 改變目標包的標題
我用第一種情況來修復配置錯誤的捆綁包,該捆綁包正在尋找一個不包含它的xml配置描述符,并且我提供了部署包含此內容的輕型Fragment Bundle。
但是我想在這里向您展示的用例是對在JBoss Fuse / Karaf上部署Byteman的方式的一種改進 。
如果你還記得我以前的帖子 ,因為Byteman類需要可從所有其他部署包,并可能需要提供訪問每一個類,我們不得不Byteman包添加到org.osgi.framework.bootdelegation屬性,指示OSGi框架通過虛擬系統捆綁包(id = 0)公開列出的軟件包 。
您可以使用headers 0來驗證當前正在使用的內容,因為它是jdk擴展和框架類的一長串,所以這里不包括輸出。
如果添加我的包org.jboss.byteman.rule,org.jboss.byteman.rule.exception ,即使這些包也會在該命令的輸出中列出。
該解決方案的問題在于,這是引導時間屬性 。 如果要使用Byteman操作已經運行的實例的字節碼,則必須在編輯此屬性后重新啟動它。
OSGi片段可以幫助您, 避免在引導時進行預配置。
我們可以構建一個沒有實際內容的自定義空捆綁包,該捆綁包將附加到系統捆綁包并擴展其服務的包列表。
<Export-Package>org.jboss.byteman.rule,org.jboss.byteman.rule.exception </Export-Package> <Fragment-Host>system.bundle; extension:=framework </Fragment-Host>這是maven-bundle-plugin插件配置的節選,請參見此處以了解完整的Maven項目 ,盡管該項目實際上只是pom.xml 30行:
JBossFuse:karaf@root> install -s mvn:test/byteman-fragment/1.0-SNAPSHOT一旦有了該配置,就可以使用Byteman,例如,在java.lang.String默認構造函數中插入一行。
# find your Fuse process id PROCESS_ID=$(ps aux | grep karaf | grep -v grep | cut -d ' ' -f2)# navigate to the folder where you have extracted Byteman cd /data/software/redhat/utils/byteman/byteman-download-2.2.0.1/# export Byteman env variable: export BYTEMAN_HOME=$(pwd) cd bin/# attach Byteman to Fabric8 process, no output expected unless you enable those verbose flags sh bminstall.sh -b -Dorg.jboss.byteman.transform.all $PROCESS_ID # add these flags if you have any kind of problem and what to see what's going on: -Dorg.jboss.byteman.debug -Dorg.jboss.byteman.verbose# install our Byteman custom rule, we are passing it directly inline with some bash trick sh bmsubmit.sh /dev/stdin <<OPTS# smoke test rule that uses also a custom output file RULE DNS StringSmokeTest CLASS java.lang.String METHOD <init>() AT ENTRY IF TRUE DO traceln(" works: " ); traceOpen("PAOLO", "/tmp/byteman.txt"); traceln("PAOLO", " works in files too " ); traceClose("PAOLO"); ENDRULEOPTS現在,要驗證Byteman是否正常運行,我們只需在Karaf shell中調用java.lang.String構造函數即可:
JBossFuse:karaf@root> new java.lang.Stringworks:按照我們的規則,您還將在/tmp/byteman.txt看到內容
第三個技巧的靈感來自OSGi Wiki和Spring的這個有趣的頁面 。
翻譯自: https://www.javacodegeeks.com/2015/02/jboss-fuse-less-known-trick.html
總結
以上是生活随笔為你收集整理的JBoss Fuse –一些鲜为人知的技巧的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 全球骑士卡是真的吗?
- 下一篇: 未确认融资费用属于什么科目?