JXSE and Equinox Tutorial, Part 2
http://java.dzone.com/articles/jxse-and-equinox-tutorial-part-0
——————————————————————————————————————————————————————
Abstract
In the first post of this series, we covered the quickest way to get JXSE 2.7x working in Equinox and, with some considerations, probably other OSGI frameworks as well. The approach aimed to get the same functionality as you would get by using the jar file in a regular JAVA setting, but as I demonstrated, Equinox does have the benefit of allowing multiple JXSE instances to run simultaneously, which is a great benefit when developing JXSE applications.
In this second tutorial, we will cover some ways of improving the functionality by severing the dependency on the 4.2x version of Jetty (which has just released it's 9.0 version!) and we will introduce some basic tools to visualize the properties and functions of JXSE. This will improve the development cycle of JXSE applications even more.
NOTE: This tutorial will use a modified JXSE jar, which currently has only been sparsely tested. If you want to develop in a fail-safe environment, I would recommend that you stick to approach of adding the 2.7x and org.mortbay.jetty 4.2x jars to your plugin structure. If you are more adventurous or, even better, want to help to improve the tooling, then this post is for you! |
Updating Jetty
The approach we covered earlier involves including a Jetty server for every JXSE bundle you want to deploy. The Jetty server is used for HTTP tunneling and basically starts a simple HTTP server with one servlet. If we want to optimize this approach when running multiple JXSE bundle projects, it would stand to reason that we run one server instance, which registers multiple servlets, which is basically the way that Jetty runs in most OSGI environments. Ideally we would utilize the http service for Equinox to register our servlets, but because every JXSE bundle needs to run on a different network port, registration of the servlets is a bit more involved.
The implication of breaking the dependency on the org.mortbay.jetty 4.2x jar (i.e. removing the jar-file from the lib directory and putting it in a separate bundle) is that the JXSE code has to be changed as well, and so we might just as well create a JXSE 2.7x bundle! This bundle will be a client for a declarative service that is offered by the Jetty plugin, and which allows registration of the specific servlets that JXSE uses. The necessary bundles can be found in the extended.zip, which offers functionality that extends the base porting of JXSE applications to Equinox. can be included in your target definition:
Download the zip-file and unpack it in the same target root as the other target plugins (e.g. C:\Projects\Target\Extended)
In the Eclipse IDE, select Window → Preferences → Plug-in Development → Target Platform, and select the active target we assembled in the previous posting
Press 'Edit' and 'Add' a new 'Directory' by selecting the appropriate controls. Browse to the folder where the unzipped files are located and add the folder to your target definition. Press 'Finish' to complete the Wizard
TIP: Extending a target definition with new directories can be a RSI-ridden chore. Luckily the 'Location' field stores previous entries, and so if you select one of these before pressing the 'Browse' button, you may win quite a few mouse-clicks |
The target definition has been extended with a number of bundles, three of which are important for this part of the tutorial:
net.jxse (2.7.x)
org.mortbay.jetty (4.2.x)
org.eclipse.jetty.jxse.bridge (1.x.y)
I try to follow the convention to use the version of a jar-file when
it is converted to OSGI, and from this it becomes evident that the first
two bundles are basically the original jar-files that were deployed in
part one of the tutorial. The only difference is that these bundles
share their dependencies through a declarative service.
NOTE: Internally, the necessary modifications |
With this, we can now modify the two JXSE Plugin project we developed
in the previous post to work with these bundles. We will also use a
different example from the book Practical JXTA II to make things more
interesting. We will try to connect Edge_Anna with Rendezvous_Jack.
Modify the two JXSE 2.7x Bundle Projects you made in the previous tutorial :
Remove the lib folder and the references to
lib/jxse-2.7.jar and
lib/org.mortbay.jetty.jar in the bundle classpath settings.
Solve the compiler errors by
importing
the necessary bundle dependencies in the 'imported packages' tab of the Manifest editor.
Include the
org.mortbay.jetty
bundle (
not
the bridge!)
The resulting Manifest.MF file should look something like this:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Practical JXTA II: Anna the Edge Peer
Bundle-SymbolicName: net.practical.jxta.decoupled.anna
Bundle-Version: 1.0.0.v20130816
Bundle-Activator: net.practical.jxta.decoupled.anna.Activator
Bundle-Vendor: MyCompany
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-ActivationPolicy: lazy
Bundle-ClassPath: .
Import-Package: net.jxta,
net.jxta.document,
net.jxta.endpoint,
net.jxta.exception,
net.jxta.id,
net.jxta.peer,
net.jxta.peergroup,
net.jxta.platform,
net.jxta.rendezvous,
org.osgi.framework;version="1.7.0"
We can now copy Edge_Anna.java and Rendezvous_Jack.javafrom the folder B_Exploring_Connectivity_Issuesfrom the examples that are covered by Practical JXTA II as replacement for the previous examples. Last we need to make a slight adjustment to the Activators in order to ensure concurrency:
import java.util.concurrent.Executors;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext; public class Activator implements BundleActivator, Runnable { private static Activator activator;
private ExecutorService executor; static Activator getDefault() {
return activator;
} public void start(BundleContext bundleContext) throws Exception {
activator = this;
executor = Executors.newSingleThreadExecutor();
executor.execute(this);
} public void stop(BundleContext bundleContext) throws Exception {
if( !executor.isShutdown() && !executor.isTerminated())
executor.shutdown();
Activator.context = null;
} @Override
public void run() {
Edge_Anna.main(null);
}
}
When the bundles are added to your run configuration, you will see that the various pop-up messages are spawned as the two bundles are activated. But hidden deep in the log messages, you will also find that a -if all went well:
INFO: Jetty Server for JXTA found!
And, a bit later:
INFO: Line 679 net.jxta.impl.peergroup.GenericPeerGroup.loadModule()
Loaded privileged module : Reference Implementation of the HTTP Message Transport
(net.jxta.impl.endpoint.servlethttp.ServletHttpTransport)
As Rendezvous_Jack is starting up HTTP transport. If
this doesn't seem to happen, then the most likely reason is that the
org.mortbay.jettybundle has not started (type 'ss' in the Eclipse
console for the status of the bundles). You can also check if the
declarative services that forge the connection between the two bundles
have started correctly by typing in the OSGI console:
'attendees': this should return (at least)
osgi> attendees
net.jxse.petitioner.ServerStarterPetitioner
org.mortbay.jetty.provider.ServerProvider'matched': this should return:
osgi> matched
net.jxse.petitioner.ServerStarterPetitioner is matched with:
org.mortbay.jetty.provider.ServerProvider
The bundles use a light-weight wrapper around OSGI's standard declarative services called a secure broker (org.eclipselabs.osgi.ds.broker)
to make the connection. This bundle is also provided by the target
addition that was downloaded .One of the added functions are three
console commands to check the connections (the third one is 'waiting').
The first command lists the (broker) services that are registered, the
second one which services are matched with one another. Above you can
see that the bunle net.jxseis connected with the bundle
org.mortbay.jetty. If these commands are not recognized, it means that
the broker plugin is not activated yet.
Integration with Jetty 6 to Jetty 8 (inclusive)
If you are a bit more adventurous, you may want to try the Jetty Bridge
that has also been included in the additions to the target. This bundle
requires the org.eclipse.jetty bundles from 6.0.0 to 8.9.9, which are
often shipped with certain Eclipse distributions. Simply deactivate the
org.mortbay.jettybundle and activate org.eclipse.jetty.jxse.bridge. (and
Jetty, of course). If all is well, you should see the same behavior as
previously, but now more recent versions of Jetty can be used.
NOTE: Please consider that I have only tested |
Enabling JXSE Tools for Eclipse
The previous examples probably have made clear that pop-up messages
and log messages are not going to be very helpful when developing
multiple JXSE Bundle projects simultaneously. Although this is work in
progress (and probably will always be so), a start has been made to
develop JXSE tools that can be used in an Eclipse IDE. I hope to add
more posts to this tutorial as functionality becomes available, but here
we can begin by demonstrating what needs to be done at minimum to make
your JXSE Bundle Projects visible to the tools.
In order to enable the Eclipse tooling, a new target is needed which
replaces equinox with an Eclipse version (which, of course, includes an
Equinox version). As we have ample experience with target definition
management by now, I will just list the three directories that are
needed to get things up and running
An Eclipse version. You can opt to copy the Kepler installation to the target environment (recommended), or use the
${eclipse-home} option as location (quickest)the core JXSE bundles that were downloaded for the previous post
The extended JXSE bundles that were downloaded for the first part of this tutorial
Next we need to create a new Eclipse application ( File → New →
Plugin Project). Select the option that the 'plug-in is targeted to run
with' an Eclipse version, and (in the second tab) that we will develop a
Rich Client application. Clicking 'Finish' will generate a bare-bones
Eclipse RCP. We will include one perspective to the RCP by hardcoding it
in the ApplicationWorkbenchAdvisor:
package org.{my-company}.jxse.ui; import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
import org.eclipse.ui.application.WorkbenchAdvisor;
import org.eclipse.ui.application.WorkbenchWindowAdvisor; public class ApplicationWorkbenchAdvisor extends WorkbenchAdvisor { private static final String PERSPECTIVE_ID = "org.eclipse.jxse.perspective"; @Override
public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(
IWorkbenchWindowConfigurer configurer) {
return new ApplicationWorkbenchWindowAdvisor(configurer);
} @Override
public String getInitialWindowPerspectiveId() {
return PERSPECTIVE_ID;
}
}
Next, remove the Tools.java file from the JXSE bundles and rename the faulty imports in the JXSE bundles to 'net.osgi.jxse.compatibility.Tools'. We also need to make some changes to the code from Practical JXTA II:
Make the class that run the examples extend net.osgi.jxse.compatibility.AbstractExampleContext
Include addModule( MyNetworkManager) after it has been instantiated;
NOTE: The static method addModule registers JXTA modules |
Last, a new launch configuration is needed for an 'Eclipse
Application'. Select the 'Run an Application' option in the first tab,
and select the application you just created. The workspace plugins that
are needed should include the application, and the two JXSE Bundle
projects 'Jack the Rendezvous' and 'Anna the Edge'. Add the 'Required
Bundles', and ensure that the following bundles are included:
org.eclipse.equinox.console
The three org.apache.felix.gogobundles
org.eclipselabs.osgi.ds.broker
org.mortbay.jetty or org.eclipse.jetty.jxse.bridge
net.osgi.jxse.compatibility
org.eclipselabs.jxse.ui
Validate the configuration and 'add Required Bundles' if necessary.
If no problems have been detected, you can launch the application. If
all went well, you should see the two JXSE bundles start up as they did
previously, but instead of the somewhat outdated pop-up boxes from JAVA
Swing, the more flashy alternatives from Eclipse's SWT packages should
pop up. Also a basic Eclipse application should become visible with some
views which are currently empty. The more observant developers will
probably spot the
WARNING:
This bundle is not a valid JXSE Bundle. A JXSE-INF directory is required.
Ignore this warning for now. It will become more important in the next part of this series.
We are almost there! Stop the run configuration, and make the following modifications to the JXSE Bundle projects:
Create a new component definition (File → New→ …) and select as the parent folder <your.bundle.name>/OSGI-INF, and name jxse.xml (or another name of your choosing). This will create a folder OSGI-INFunder the root of your JXSE bundles and add the file.
When the component editor opens, fill in the details as follows:
1.
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
2.
<
scr:component
xmlns:scr
=
"http://www.osgi.org/xmlns/scr/v1.1.0"
name="<your.bundle.name>.service">
3.
<
implementation
class="<your.bundle.name>.service.OsgiComponent"/>
4.
<
reference
bind
=
"setAttendeeService"
cardinality
=
"1..1"
interface
=
"org.eclipselabs.osgi.ds.broker.IAttendeeService"
name
=
"IAttendeeService"
policy
=
"static"
unbind
=
"unsetAttendeeService"
/>
5.
</
scr:component
>
After the component definition is completed, the required OsgiComponent.java needs to be present in the designated package. This class should look as follows:
1.
<?xml version=
"1.0"
encoding=
"UTF-8"
?>
2.
<scr:component xmlns:scr=
"http://www.osgi.org/xmlns/scr/v1.1.0"
name=
"<your.bundle.name>.service"
>
3.
<implementation
class
=
"<your.bundle.name>.service.OsgiComponent"
/>
4.
<reference bind=
"setAttendeeService"
cardinality=
"1..1"
interface
=
"org.eclipselabs.osgi.ds.broker.IAttendeeService"
name=
"IAttendeeService"
policy=
"static"
unbind=
"unsetAttendeeService"
/>
5.
</scr:component>
Include the following line in the Manifest-MF file:
Service-Component: OSGI-INF/jxse.xml
- The OsgiComponent is very simple:
01.
package
<your.bundle.name>;
02.
03.
import
net.osgi.jxse.service.core.JxseDSComponent;
04.
import
<your.bundle.name>.Activator;
05.
06.
public
class
OsgiComponent
extends
JxseDSComponent {
07.
08.
public
OsgiComponent() {
09.
super
( Activator.getDefault());
10.
}
11.
}
Modify the Activator as follows:
01. package <your.bundle.name>; 02. 03. import org.osgi.framework.BundleActivator; 04. import org.osgi.framework.BundleContext; 05. 06. public class Activator extends AbstractJxseBundleActivator{ 07. 08. private static Activator activator; 09. 10. static Activator getDefault() { 11. return activator; 12. } 13. 14. public void start(BundleContext bundleContext) throws Exception { 15. activator = this ; 16. } 17. 18. public void stop(BundleContext bundleContext) throws Exception { 19. activator = null ; 20. } 21. 22. @Override 23. public IJxseServiceContext<NetworkManager> createContext(){ 24. return new Edge_Anna(); 25. } 26. } |
As you can see, the Activator has become much simpler, as the
superclass it derives from does most of the work. All that needs to be
done is to tell the activator which IJxseServiceContextis required, and
these rest is taken care of. The OsgiComponentextracts the context from
the Activator and offers it as a declarative service.
If the changes compile without problems, you can launch the
application, and if all went well, you should now see both JXSE bundles
become visible in the navigator at the left-hand side of the GUI.
Clicking these should show you the NetworkManager,
NetworkConfiguratorand the NetPeerGroup, while their properties are
displayed in the properties editor.
NOTE: Currently not |
Securing your JXSE Bundle
When deploying your bundle in a production environment, you have to
consider that the declarative service opens up means for 'rogue bundles'
to listen to the creation and deployment of your JXSE bundle. As this
poses a security risk, it is advised to disable the declarative service
before deployment in real-world settings. You can either remove the
Service-Component entry in the manifest file in order to achieve this.
In the next tutorial I will cover a different way of securing the
declarative service.
Conclusion
This tutorial has demonstrated some improvements on the results of the previous posting,
and has opened up a way to view the content of the JXSE Bundles. So
far, the main focus has been to modify existing code in order to get it
working in Eclipse / Equinox. The next post will concentrate on building
a JXSE bundle from scratch, and mixed-method approaches.
JXSE and Equinox Tutorial, Part 2的更多相关文章
- JXSE and Equinox Tutorial, Part 1
http://java.dzone.com/articles/jxse-and-equinox-tutorial-part —————————————————————————————————————— ...
- 基于Equinox构建OSGi项目
几种OSGi框架 Several independently implemented OSGi frameworks exist today, including four that are avai ...
- [翻译+山寨]Hangfire Highlighter Tutorial
前言 Hangfire是一个开源且商业免费使用的工具函数库.可以让你非常容易地在ASP.NET应用(也可以不在ASP.NET应用)中执行多种类型的后台任务,而无需自行定制开发和管理基于Windows ...
- Django 1.7 Tutorial 学习笔记
官方教程在这里 : Here 写在前面的废话:)) 以前学习新东西,第一想到的是找本入门教程,按照书上做一遍.现在看了各种网上的入门教程后,我觉得还是看官方Tutorial靠谱.书的弊端一说一大推 本 ...
- thrift 服务端linux C ++ 与客户端 windows python 环境配置(thrift 自带tutorial为例)
关于Thrift文档化的确是做的不好.摸索了很久才终于把跨linux与windows跨C++与python语言的配置成功完成.以下是步骤: 1) Linux下环境配置 ...
- Hive Tutorial(上)(Hive 入门指导)
用户指导 Hive 指导 Hive指导 概念 Hive是什么 Hive不是什么 获得和开始 数据单元 类型系统 内置操作符和方法 语言性能 用法和例子(在<下>里面) 概念 Hive是什么 ...
- Home / Python MySQL Tutorial / Calling MySQL Stored Procedures in Python Calling MySQL Stored Procedures in Python
f you are not familiar with MySQL stored procedures or want to review it as a refresher, you can fol ...
- Using FreeMarker templates (FTL)- Tutorial
Lars Vogel, (c) 2012, 2016 vogella GmbHVersion 1.4,06.10.2016 Table of Contents 1. Introduction to F ...
- Oracle Forms 10g Tutorial Ebook Download - Oracle Forms Blog
A step by step tutorial for Oracle Forms 10g development. This guide is helpful for freshers in Orac ...
随机推荐
- Miller_Rabin (米勒-拉宾) 素性测试
之前一直对于这个神奇的素性判定方法感到痴迷而又没有时间去了解.借着学习<信息安全数学基础>将素性这一判定方法学习一遍. 首先证明一下费马小定理. 若p为素数,且gcd(a, p)=1, 则 ...
- cocoStudio UI编辑器 学习总结
一.控件 控件基类 UIWidget:所有UI控件的基类 addChild:添加UIWidget类型的节点 addRenderer:添加CCNode类型的节点 所有UIWidget,都可以设置成触摸s ...
- C的输入输出函数的基本用法
printf输出函数: printf()函数是格式化输出函数, 一般用于向标准输出设备按规定格式输出信息. printf()函数的调用格式为: printf("<格式化字符串>& ...
- maven整合s2sh截图
- concat、reverse面试题
1.concat数组连接 ,,]; ,,]; ,,]; alert(arr3.concat(arr1,arr2)); 结果:9,9,9,2,3,4,5,6,7 2.reverse将数组内容颠个个 ,, ...
- html:唤起手机qq开始对话 & 自动拨号
<a href="mqqwpa://im/chat?chat_type=wpa&uin=[qq号]&version=1">XXX</a> 另 ...
- hdu 5510 Bazinga (kmp+dfs剪枝) 2015ACM/ICPC亚洲区沈阳站-重现赛(感谢东北大学)
废话: 这道题很是花了我一番功夫.首先,我不会kmp算法,还专门学了一下这个算法.其次,即使会用kmp,但是如果暴力枚举的话,还是毫无疑问会爆掉.因此在dfs的基础上加上两次剪枝解决了这道题. 题意: ...
- hdu 1074(状态压缩dp+记录路径)
题意:给了n个家庭作业,然后给了每个家庭作业的完成期限和花费的实践,如果完成时间超过了期限,那么就要扣除分数,然后让你找出一个最优方案使扣除的分数最少,当存在多种方案时,输出字典序最小的那种,因为题意 ...
- nginx修改内核参数
1.修改用户进程可打开文件数限制 在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件 数量的限制(这是因为系统为 ...
- OS X中如何获取当前运行程序的路径
OS X的执行程序一般分为两种.一种是控制台程序,一种是带有GUI的OS X应用程序. 控制台程序往往就一个文件构成executable,而GUI应用通常是一个包(即文件夹),里面除了executab ...